nt9856x/code/application/sifarsdk/hal/Usb.cpp

322 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}