322 lines
7.7 KiB
C++
322 lines
7.7 KiB
C++
#include "Usb.h"
|
||
#include "Log.h"
|
||
#include "linux_api.h"
|
||
#include <thread>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <unistd.h>
|
||
#include <fcntl.h>
|
||
#include <termios.h>
|
||
Usb::Usb()
|
||
{
|
||
TtyUSB2Fd = -1;
|
||
UartFd = -1;
|
||
}
|
||
SINT32 Usb::Init(SF_SERIAL_DATA_FRAME_TYPE_S usbNode)
|
||
{
|
||
SINT32 ret = SF_FAILURE;
|
||
if (TtyUSB2Fd > 0)
|
||
{
|
||
LogError("[/dev/ttyUSB2] has already inited !!!\n");
|
||
return SF_FAILURE;
|
||
}
|
||
if (!usbNode.node)
|
||
{
|
||
LogError("Node path is nullptr !!!\n");
|
||
return SF_FAILURE;
|
||
}
|
||
ret = Create(usbNode.node, &usbNode, &TtyUSB2Fd);
|
||
return ret;
|
||
}
|
||
SINT32 Usb::UnInit(void)
|
||
{
|
||
if (TtyUSB2Fd < 0)
|
||
{
|
||
LogInfo("[/dev/ttyUSB2] has already deinited !!!\n");
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
return Destory();
|
||
}
|
||
SINT32 Usb::Write(const SF_CHAR *sendBuf, SINT32 dataLen)
|
||
{
|
||
SINT32 len = 0;
|
||
|
||
len = linux_write(UartFd, sendBuf, dataLen);
|
||
if (len == dataLen)
|
||
{
|
||
return SF_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
tcflush(UartFd, TCOFLUSH);
|
||
LogError("write fail!\n");
|
||
return SF_FAILURE;
|
||
}
|
||
}
|
||
SINT32 Usb::Read(SF_CHAR *recvBuf, SINT32 dataLen, const unsigned int &retryTimes)
|
||
{
|
||
// SF_PDT_PARAM_CFG_S *sfParam = sf_customer_param_get();
|
||
SINT32 s32ret = 0;
|
||
fd_set read_fds;
|
||
struct timeval TimeoutVal;
|
||
// TODO: 这个函数需要整改
|
||
unsigned int retry = retryTimes;
|
||
if (retry > 0)
|
||
// sf_sleep_ms(retry);
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // TODO: Need to test to confirm the time parameter.
|
||
|
||
while (retry--)
|
||
{
|
||
|
||
FD_ZERO(&read_fds);
|
||
FD_SET(UartFd, &read_fds);
|
||
|
||
TimeoutVal.tv_sec = 0;
|
||
TimeoutVal.tv_usec = 10000;
|
||
|
||
s32ret = select(UartFd + 1, &read_fds, NULL, NULL, &TimeoutVal); // TODO: 不用设置阻塞模式?
|
||
if (s32ret > 0)
|
||
{
|
||
if (FD_ISSET(UartFd, &read_fds))
|
||
{
|
||
s32ret = linux_read(UartFd, recvBuf, 580); // TODO: 这里有可能读不到580的长度
|
||
if (s32ret > 0)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
FD_CLR(UartFd, &read_fds);
|
||
}
|
||
else if (s32ret < 0)
|
||
{
|
||
// LogInfo(" select failed\n");
|
||
continue;
|
||
}
|
||
else if (0 == s32ret)
|
||
{
|
||
// LogInfo("FIFO select timeout [%d]\n",retry);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
return SF_SUCCESS;
|
||
}
|
||
bool Usb::IsUsbWorking(void)
|
||
{
|
||
return TtyUSB2Fd > 0 ? true : false;
|
||
}
|
||
SINT32 Usb::Create(const SF_CHAR *ttyusbName, SF_SERIAL_DATA_FRAME_TYPE_S *pSerialAttr, SINT32 *pttyfd)
|
||
{
|
||
// LogInfo("Create usb fd, ttyusbName = %s.\n", ttyusbName);
|
||
SINT32 ret = SF_FAILURE;
|
||
SINT8 i = 0;
|
||
while (i < 2)
|
||
{
|
||
if (SF_FAILURE < (*pttyfd = OpenUsb(ttyusbName)))
|
||
break;
|
||
i++;
|
||
// usleep(100000);
|
||
// TODO: 用nanoseconds可行?
|
||
std::this_thread::sleep_for(std::chrono::nanoseconds(100));
|
||
}
|
||
|
||
if (*pttyfd <= 0)
|
||
return SF_FAILURE;
|
||
|
||
ret = Config(*pttyfd, pSerialAttr);
|
||
if (SF_FAILURE == ret)
|
||
{
|
||
LogError("config [%s] Fail!\n", ttyusbName);
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
SINT32 Usb::OpenUsb(const SF_CHAR *deviceName)
|
||
{
|
||
SINT16 ret = -1;
|
||
// SINT32 UartFd = -1;
|
||
UartFd = linux_open(deviceName, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||
if (-1 == UartFd)
|
||
{
|
||
// LogError("Open usb failed node = %s, fd = %d error = %ld.\n", deviceName, UartFd, errno);
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
ret = linux_fcntl(UartFd, F_SETFL, 0);
|
||
if (ret < 0)
|
||
{
|
||
LogError("fcntl failed!\n");
|
||
return SF_FAILURE;
|
||
}
|
||
LogInfo("UartFd = %d\n", UartFd);
|
||
return UartFd;
|
||
}
|
||
SINT32 Usb::Config(SINT32 UartFd, SF_SERIAL_DATA_FRAME_TYPE_S *pSerialAttr)
|
||
{
|
||
|
||
unsigned int i;
|
||
SINT32 speed_arr[] = {B115200, B460800};
|
||
SINT32 name_arr[] = {115200, 460800};
|
||
struct termios options;
|
||
if (tcgetattr(UartFd, &options) != 0)
|
||
{
|
||
LogError("SetupSerial 1");
|
||
return SF_FAILURE;
|
||
}
|
||
for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
|
||
{
|
||
if (pSerialAttr->speed == name_arr[i])
|
||
{
|
||
cfsetispeed(&options, speed_arr[i]);
|
||
cfsetospeed(&options, speed_arr[i]);
|
||
}
|
||
}
|
||
#if 1
|
||
|
||
switch (pSerialAttr->flow_ctrl)
|
||
{
|
||
case 'n':
|
||
case 'N': // 不使用流控制
|
||
options.c_cflag &= ~(600); // CRTSCTS;
|
||
break;
|
||
|
||
case 'h':
|
||
case 'H': // 使用硬件流控制
|
||
options.c_cflag |= 600; // CRTSCTS;
|
||
break;
|
||
|
||
case 'S':
|
||
case 's': // 使用软件流控制
|
||
options.c_cflag |= IXON | IXOFF | IXANY;
|
||
break;
|
||
}
|
||
|
||
// 设置数据位
|
||
options.c_cflag &= ~CSIZE; // 屏蔽其他标志位
|
||
|
||
switch (pSerialAttr->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:
|
||
fprintf(stderr, "Unsupported data size/n");
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
// 设置校验位
|
||
switch (pSerialAttr->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:
|
||
fprintf(stderr, "Unsupported parity/n");
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
// 设置停止位
|
||
switch (pSerialAttr->stopbits)
|
||
{
|
||
case 1:
|
||
options.c_cflag &= ~CSTOPB;
|
||
break;
|
||
|
||
case 2:
|
||
options.c_cflag |= CSTOPB;
|
||
break;
|
||
|
||
default:
|
||
fprintf(stderr, "Unsupported stop bits/n");
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
// 修改输出模式,原始数据输出
|
||
options.c_oflag &= ~OPOST;
|
||
|
||
// 激活配置 (将修改后的termios数据设置到串口中)
|
||
if (tcsetattr(UartFd, TCSANOW, &options) != 0)
|
||
{
|
||
LogError("com set error!/n");
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||
|
||
// 设置等待时间和最小接收字符
|
||
options.c_cc[VTIME] = 0;
|
||
options.c_cc[VMIN] = 1;
|
||
|
||
// 如果发生数据溢出,接收数据,但是不再读取
|
||
tcflush(UartFd, TCIFLUSH);
|
||
#endif
|
||
|
||
// 激活配置 (将修改后的termios数据设置到串口中)
|
||
if (tcsetattr(UartFd, TCSANOW, &options) != 0)
|
||
{
|
||
LogError("com set error!/n");
|
||
return SF_FAILURE;
|
||
}
|
||
|
||
return SF_SUCCESS;
|
||
}
|
||
SINT32 Usb::Destory(void)
|
||
{
|
||
int ret = 0;
|
||
int count = 0;
|
||
if (UartFd < 0)
|
||
{
|
||
LogWarning("UartFd < 0\n");
|
||
return SF_SUCCESS;
|
||
}
|
||
while ((ret = linux_close(UartFd)) < 0)
|
||
{
|
||
std::this_thread::sleep_for(std::chrono::nanoseconds(100));
|
||
count++;
|
||
if (count > 10)
|
||
{
|
||
LogError("Close USB File Failed.\n");
|
||
break;
|
||
}
|
||
}
|
||
return ret;
|
||
} |