#include "Usb.h" #include "Log.h" #include "linux_api.h" #include #include #include #include #include #include #include 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; }