blob: 45f932ff124705a21d3fd1d43b001a7065909366 [file] [log] [blame]
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include "LogInfo.h"
#include "CSerial.h"
/*******************************************************************************
* 宏定义 *
*******************************************************************************/
#define DEV_RSP_COUNT (1024)
/*******************************************************************************
* 全局变量 *
*******************************************************************************/
static int m_fd;
static char rspBufex[DEV_RSP_COUNT] = {0};
/*******************************************************************************
* 函数声明 *
*******************************************************************************/
static ssize_t SendAT(const char *pData, size_t length);
static ssize_t ReadAT(BYTE *pbyReadBuffer, size_t dwReadCount);
/*******************************************************************************
* 内部函数 *
*******************************************************************************/
/**
* @brief 发送AT命令
* @param pData 入参,AT命令写入缓冲区
* @param length 入参,AT命令长度
* @return 成功返回成功写入的字节数,失败返回-1
* @retval
* @note length不计算结尾\0
* @warning
*/
static ssize_t SendAT(const char *pData, size_t length)
{
ssize_t dwBytesWritten = -1;
ssize_t writeCount = 0;
struct timeval timeout;
fd_set fds, temps;
int result = 0;
if (m_fd < 0)
{
return -1;
}
if (pData != NULL)
{
LogInfo("pData= (%s) length = %ld ", pData, length);
}
// gettimeofday(&end, NULL);
// gettimeofday(&begin, NULL);
FD_ZERO(&fds);
FD_SET(m_fd, &fds);
/* 超时不能在此设置!
因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
调用select函数前,每次都需要初始化timeval结构体变量.
timeout.tv_sec = 1;
timeout.tv_usec = 0; */
while (1)
{
/* 将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
temps = fds;
// 设置超时
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// 调用select函数
result = select(m_fd + 1, NULL, &temps, NULL, &timeout);
if (result <= 0)
{
if (0 == result)
{
LogInfo("timeout");
}
else
{
LogInfo("select() error");
}
break;
// return -1;
}
else
{
// 判断m_fd是否可写,若可写,写入数据
if (FD_ISSET(m_fd, &temps))
{
dwBytesWritten = write(m_fd, pData + writeCount, length - writeCount);
LogInfo("pData= (%s) dwBytesWritten = %ld ", pData, dwBytesWritten);
if (dwBytesWritten > 0)
{
writeCount += dwBytesWritten;
if (writeCount >= length)
{
break;
}
}
if (dwBytesWritten < 0 && errno != EINTR)
{
printf("SendAT:: write error, dwBytesWritten = %ld, %s\r\n", dwBytesWritten, strerror(errno));
break;
}
}
}
}
if (dwBytesWritten > 0)
{
return dwBytesWritten;
}
else
{
return -1;
}
}
/**
* @brief 接收AT命令应答
* @param pbyReadBuffer 出参,应答读取缓冲区
* @param dwReadCount 入参,应答读取长度
* @return 成功返回成功写入的字节数,失败返回-1
* @retval
* @note
* @warning
*/
static ssize_t ReadAT(BYTE *pbyReadBuffer, size_t dwReadCount)
{
ssize_t dwBytesRead = -1;
ssize_t readCount = 0;
int result;
fd_set fds, temps;
struct timeval timeout;
if (m_fd < 0)
{
return -1;
}
LogInfo("ReadAT start");
FD_ZERO(&fds);
FD_SET(m_fd, &fds);
while (1)
{
temps = fds;
// 设置超时
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// 调用select函数
result = select(m_fd + 1, &temps, NULL, NULL, &timeout);
if (result <= 0)
{
if (0 == result)
{
LogInfo("timeout");
}
else
{
LogInfo("select() error");
}
return -1;
}
else
{
// 判断m_fd是否可读,若可读,读取数据
if (FD_ISSET(m_fd, &temps))
{
dwBytesRead = read(m_fd, pbyReadBuffer + readCount, dwReadCount - readCount);
LogInfo("pData= (%s) dwBytesWritten = %ld ", pbyReadBuffer, dwBytesRead);
if (dwBytesRead > 0)
{
readCount += dwBytesRead;
if (readCount >= dwReadCount)
{
break;
}
}
if (dwBytesRead < 0 && errno != EINTR)
{
printf("ReadAT::read error, dwBytesRead = %ld, %s\r\n", dwBytesRead, strerror(errno));
break;
}
}
}
}
if (dwBytesRead > 0)
{
return dwBytesRead;
}
else
{
return -1;
}
}
/*******************************************************************************
* 外部函数 *
*******************************************************************************/
/**
* @brief 打开设备文件,并设置波特率等参数
* @param portName 入参,端口名
* @return 成功返回0,失败返回-1
* @retval
* @note
* @warning
*/
int Open(const char *portName)
{
// char portname_full[20] = "/dev/";
// strcat(portname_full, portName);
// portName = +portName ;
struct termios attr;
int flags;
if (portName != NULL)
{
LogInfo("portname = (%s)", portName);
}
m_fd = open(portName, O_RDWR | O_NONBLOCK | O_NOCTTY | O_TRUNC);
if (m_fd < 0)
{
LogInfo("Open m_fd < 0 m_fd = %d\n", m_fd);
return -1;
}
else
{
LogInfo("Open m_fd > 0 m_fd = %d\n", m_fd);
}
tcflush(m_fd, TCIOFLUSH); // clear serial data
if (tcgetattr(m_fd, &attr) < 0)
{
close(m_fd);
return -1;
}
attr.c_iflag = IXON | IXOFF;
attr.c_oflag = 0;
attr.c_cflag &= ~(CSIZE | CFLAGS_TO_CLEAR | CFLAGS_HARDFLOW);
attr.c_cflag |= (CS8 | CFLAGS_TO_SET);
attr.c_cflag |= CFLAGS_HARDFLOW;
attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ISIG);
attr.c_lflag &= ~OPOST;
int i;
#ifdef _POSIX_VDISABLE
attr.c_cc[0] = _POSIX_VDISABLE;
#else
attr.c_cc[0] = fpathconf(m_fd, _PC_VDISABLE);
#endif
for (i = 1; i < NCCS; i++)
{
attr.c_cc[i] = attr.c_cc[0];
}
attr.c_cc[VMIN] = 0;
attr.c_cc[VTIME] = 5;
cfsetispeed(&attr, BAUDRATE);
cfsetospeed(&attr, BAUDRATE);
if (tcsetattr(m_fd, TCSANOW, &attr) < 0)
{
close(m_fd);
return -1;
}
flags = fcntl(m_fd, F_GETFL, 0);
if (flags < 0)
{
close(m_fd);
return -1;
}
if (fcntl(m_fd, F_SETFL, flags) < 0)
{
close(m_fd);
return -1;
}
// m_isOpen = true;
// StartRead();
return 0;
}
/**
* @brief 关闭设备文件
* @param 无
* @return 成功关闭返回0,否则返回-1
* @retval
* @note
* @warning
*/
int Close()
{
tcflush(m_fd, TCIOFLUSH); // clear serial data
if (m_fd > 0)
{
// printf("close m_fd\n");
close(m_fd);
}
else
{
printf("%s:: close->else\n", __FUNCTION__);
return -1;
}
m_fd = 0;
return 0;
}
/**
* @brief 发送AT命令并读取返回值
* @param Dev_tty 入参,打开的AT口设备路径
* @param AtString 入参,发送的AT命令字符串
* @param RebackString 出参,AT命令返回的字符串
* @return 成功返回0,失败返回-1
* @retval
* @note
* @warning
*/
int SendATString(const char *Dev_tty, const char *AtString, char *RebackString)
{
BYTE tmp[1024] = {0};
printf("%s:: Before Open port, (%s)\n", __FUNCTION__, Dev_tty);
if (-1 == (Open(Dev_tty)))
{
if (AtString != NULL)
{
LogInfo("SendATString Failed AtString = (%s)", AtString);
}
printf("%s:: Open port error\r\n", __FUNCTION__);
return -1;
}
if (AtString != NULL)
{
LogInfo("SendATString OK, AtString = (%s)", AtString);
}
LogInfo("Before SendAT");
if(SendAT(AtString, strlen(AtString)) < 0)
{
LogInfo("SendAT failed");
Close();
return -1;
}
LogInfo("After SendAT");
ReadAT(tmp, 1024);
LogInfo("out ReadAT");
memcpy(RebackString, tmp, 1024);
LogInfo("after memcpy");
Close();
return 0;
}
/**
* @brief 发送数据
* @param pbyWriteBuffer 入参,写入数据缓冲区
* @param dwWriteCount 入参,写入数据长度
* @param dwSleepAfterAction 入参,
* @param dwTimeoutCount 入参,超时时间,单位秒
* @return 成功返回TRUE,失败返回FALSE
* @retval
* @note
* @warning
*/
BOOL SendData(const BYTE *pbyWriteBuffer, size_t dwWriteCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
{
ssize_t sBytesWritten = -1;
ssize_t writeCount = 0;
struct timeval timeout;
fd_set fds, temps;
int result = 0;
// int count = 0; // 超时计数
LogInfo("writecount %d, timeout %d s", dwWriteCount, dwTimeoutCount);
if (m_fd < 0)
{
LogInfo("m_fd < 0");
return FALSE;
}
FD_ZERO(&fds);
FD_SET(m_fd, &fds);
tcflush(m_fd, TCIOFLUSH); // clear serial data
if (dwTimeoutCount < 10)
{
dwTimeoutCount = 10;
}
/* 超时不能在此设置!
因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
调用select函数前,每次都需要初始化timeval结构体变量.
timeout.tv_sec = 1;
timeout.tv_usec = 0; */
while (1)
{
/*将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
temps = fds;
// 设置超时
timeout.tv_sec = dwTimeoutCount;
timeout.tv_usec = 0;
// 调用select函数
result = select(m_fd + 1, NULL, &temps, NULL, &timeout);
LogInfo("select result = %d ", result);
if (-1 == result)
{
LogInfo("select() error\n");
perror("SendData:: select() error\n");
break;
}
else if (0 == result)
{
puts("SendData:: timeout\r\n");
break;
}
else
{
// 判断m_fd是否可写,若可写,写入数据
if (FD_ISSET(m_fd, &temps))
{
sBytesWritten = write(m_fd, (char *)pbyWriteBuffer + writeCount, dwWriteCount - writeCount);
LogInfo("pbyWriteBuffer= (%s) dwBytesWritten = %ld ", pbyWriteBuffer, sBytesWritten);
if (sBytesWritten > 0)
{
writeCount += sBytesWritten;
if (writeCount >= dwWriteCount)
{
return TRUE; // complete success
}
}
else
{
if (sBytesWritten < 0 && errno != EINTR)
{
printf("SendData::write error, dwBytesWritten = %ld, %s\r\n", sBytesWritten, strerror(errno));
}
return FALSE;
}
}
}
}
return FALSE;
}
/**
* @brief 接收数据
* @param pbyReadBuffer 入参,读取数据缓冲区
* @param dwReadCount 入参,读取数据长度
* @param dwSleepAfterAction 入参,
* @param dwTimeoutCount 入参,超时时间,单位秒
* @return 成功返回TRUE,失败返回FALSE
* @retval
* @note
* @warning
*/
BOOL ReadData(BYTE *pbyReadBuffer, size_t dwReadCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
{
ssize_t sBytesReadn = -1;
ssize_t readCount = 0;
int result;
fd_set fds, temps;
struct timeval timeout;
// int readCount = 0;
// int count = 0; // 超时计数
LogInfo("ReadData reacount %d, timeout %d s\n", dwReadCount, dwTimeoutCount);
if (m_fd < 0)
{
LogInfo("m_fd < 0");
return -1;
}
FD_ZERO(&fds);
FD_SET(m_fd, &fds);
if (dwTimeoutCount < 10)
{
dwTimeoutCount = 10;
}
while (1)
{
temps = fds;
timeout.tv_sec = dwTimeoutCount;
timeout.tv_usec = 0;
result = select(m_fd + 1, &temps, NULL, NULL, &timeout);
LogInfo("select result = %d ", result);
if (-1 == result)
{
LogInfo("select() error\n");
perror("ReadData:: select() error\n");
break;
}
else if (0 == result)
{
puts("ReadData:: timeout\n");
break;
}
else
{
// 判断m_fd是否可读,若可读,读取数据
if (FD_ISSET(m_fd, &temps))
{
sBytesReadn = read(m_fd, pbyReadBuffer + readCount, dwReadCount - readCount);
LogInfo("pbyReadBuffer= (%s) sBytesReadn = %ld ", pbyReadBuffer, sBytesReadn);
if (sBytesReadn > 0)
{
readCount += sBytesReadn;
if (readCount >= dwReadCount)
{
return TRUE; // complete success
}
}
else
{
if (sBytesReadn < 0 && errno != EINTR)
{
printf("ReadData::read error, sBytesReadn = %ld, %s\r\n", sBytesReadn, strerror(errno));
}
return FALSE;
}
}
}
}
return FALSE;
}
/**
* @brief 接收数据缓冲
* @param dwReadCount 入参,读取数据长度
* @param dwSleepAfterAction 入参,
* @param dwTimeoutCount 入参,超时时间,单位秒
* @return 成功返回读取的数据指针,失败返回NULL
* @retval
* @note
* @warning
*/
BYTE *ReadDataExtraFuncB(DWORD dwReadCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
{
ssize_t sBytesReadn = -1;
ssize_t readCount = 0;
int result;
fd_set fds, temps;
struct timeval timeout;
LogInfo("readcount %d, timeout %d s", dwReadCount, dwTimeoutCount);
memset(rspBufex, 0, DEV_RSP_COUNT);
if (m_fd < 0)
{
LogInfo("m_fd < 0");
return rspBufex;
}
FD_ZERO(&fds);
FD_SET(m_fd, &fds);
if (dwTimeoutCount < 10)
{
dwTimeoutCount = 10;
}
while (1)
{
temps = fds;
timeout.tv_sec = dwTimeoutCount;
timeout.tv_usec = 0;
result = select(m_fd + 1, &fds, NULL, NULL, &timeout);
LogInfo("select result = %d ", result);
if (-1 == result)
{
LogInfo("select() error\n");
perror("ReadDataExtraFuncB:: select() error\n");
break;
}
else if (0 == result)
{
puts("ReadDataExtraFuncB:: timeout\n");
break;
}
else
{
// 判断m_fd是否可读,若可读,读取数据
if (FD_ISSET(m_fd, &temps))
{
sBytesReadn = read(m_fd, rspBufex + readCount, DEV_RSP_COUNT - readCount);
LogInfo("pbyReadBuffer= (%s) sBytesReadn = %ld ", rspBufex, sBytesReadn);
if (sBytesReadn > 0)
{
readCount += sBytesReadn;
printf("ReadDataExtraFuncB:: readCount = %ld, dwReadCount = %d \r\n", readCount, dwReadCount);
if (readCount >= dwReadCount)
{
break; // complete success
}
}
else
{
if (sBytesReadn < 0 && errno != EINTR)
{
printf("ReadData::read error, sBytesReadn = %ld, %s\r\n", sBytesReadn, strerror(errno));
}
break;
}
}
}
}
LogInfo("rspBufex = (%s)", rspBufex);
return rspBufex;
}