1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci 16cc290419Sopenharmony_ci#ifdef HDC_SUPPORT_UART 17cc290419Sopenharmony_ci 18cc290419Sopenharmony_ci#include "uart.h" 19cc290419Sopenharmony_ci#ifdef HOST_MAC 20cc290419Sopenharmony_ci#include <fcntl.h> 21cc290419Sopenharmony_ci#include <sys/ioctl.h> 22cc290419Sopenharmony_ci#include <IOKit/serial/ioss.h> 23cc290419Sopenharmony_ci#define B1500000 1500000 24cc290419Sopenharmony_ci#define B921600 921600 25cc290419Sopenharmony_ci#endif 26cc290419Sopenharmony_ci 27cc290419Sopenharmony_ciusing namespace std::chrono; 28cc290419Sopenharmony_cinamespace Hdc { 29cc290419Sopenharmony_ciExternInterface HdcUARTBase::defaultInterface; 30cc290419Sopenharmony_ci 31cc290419Sopenharmony_civoid ExternInterface::SetTcpOptions(uv_tcp_t *tcpHandle) 32cc290419Sopenharmony_ci{ 33cc290419Sopenharmony_ci return Base::SetTcpOptions(tcpHandle); 34cc290419Sopenharmony_ci} 35cc290419Sopenharmony_ci 36cc290419Sopenharmony_ciint ExternInterface::SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int len) 37cc290419Sopenharmony_ci{ 38cc290419Sopenharmony_ci return Base::SendToStream(handleStream, buf, len); 39cc290419Sopenharmony_ci} 40cc290419Sopenharmony_ci 41cc290419Sopenharmony_ciint ExternInterface::SendToPollFd(int fd, const uint8_t *buf, const int len) 42cc290419Sopenharmony_ci{ 43cc290419Sopenharmony_ci return Base::SendToPollFd(fd, buf, len); 44cc290419Sopenharmony_ci} 45cc290419Sopenharmony_ci 46cc290419Sopenharmony_ciint ExternInterface::UvTcpInit(uv_loop_t *loop, uv_tcp_t *tcp, int socketFd) 47cc290419Sopenharmony_ci{ 48cc290419Sopenharmony_ci if (uv_tcp_init(loop, tcp) == 0) { 49cc290419Sopenharmony_ci return uv_tcp_open(tcp, socketFd); 50cc290419Sopenharmony_ci } else { 51cc290419Sopenharmony_ci return -1; 52cc290419Sopenharmony_ci } 53cc290419Sopenharmony_ci} 54cc290419Sopenharmony_ci 55cc290419Sopenharmony_ciint ExternInterface::UvRead(uv_stream_t *stream, uv_alloc_cb allocCallBack, uv_read_cb readCallBack) 56cc290419Sopenharmony_ci{ 57cc290419Sopenharmony_ci return uv_read_start(stream, allocCallBack, readCallBack); 58cc290419Sopenharmony_ci} 59cc290419Sopenharmony_ci 60cc290419Sopenharmony_ciint ExternInterface::StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, 61cc290419Sopenharmony_ci uv_after_work_cb pFuncAfterThread, void *pThreadData) 62cc290419Sopenharmony_ci{ 63cc290419Sopenharmony_ci return Base::StartWorkThread(loop, pFuncWorkThread, pFuncAfterThread, pThreadData); 64cc290419Sopenharmony_ci} 65cc290419Sopenharmony_ci 66cc290419Sopenharmony_civoid ExternInterface::TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack) 67cc290419Sopenharmony_ci{ 68cc290419Sopenharmony_ci return Base::TryCloseHandle(handle, closeCallBack); 69cc290419Sopenharmony_ci} 70cc290419Sopenharmony_ci 71cc290419Sopenharmony_cibool ExternInterface::TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb) 72cc290419Sopenharmony_ci{ 73cc290419Sopenharmony_ci return Base::TimerUvTask(loop, data, cb); 74cc290419Sopenharmony_ci} 75cc290419Sopenharmony_cibool ExternInterface::UvTimerStart(uv_timer_t *handle, uv_timer_cb cb, uint64_t timeout, 76cc290419Sopenharmony_ci uint64_t repeat) 77cc290419Sopenharmony_ci{ 78cc290419Sopenharmony_ci return uv_timer_start(handle, cb, timeout, repeat); 79cc290419Sopenharmony_ci} 80cc290419Sopenharmony_ci 81cc290419Sopenharmony_cibool ExternInterface::DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, 82cc290419Sopenharmony_ci void *data, DelayCB cb) 83cc290419Sopenharmony_ci{ 84cc290419Sopenharmony_ci return Base::DelayDo(loop, delayMs, flag, msg, data, cb); 85cc290419Sopenharmony_ci} 86cc290419Sopenharmony_ci 87cc290419Sopenharmony_ciHdcUARTBase::HdcUARTBase(HdcSessionBase &sessionBaseIn, ExternInterface &interfaceIn) 88cc290419Sopenharmony_ci : externInterface(interfaceIn), sessionBase(sessionBaseIn) 89cc290419Sopenharmony_ci{ 90cc290419Sopenharmony_ci uartOpened = false; 91cc290419Sopenharmony_ci} 92cc290419Sopenharmony_ci 93cc290419Sopenharmony_ciHdcUARTBase::~HdcUARTBase(void) {} 94cc290419Sopenharmony_ci 95cc290419Sopenharmony_ci#ifndef _WIN32 96cc290419Sopenharmony_ciint HdcUARTBase::GetUartSpeed(int speed) 97cc290419Sopenharmony_ci{ 98cc290419Sopenharmony_ci switch (speed) { 99cc290419Sopenharmony_ci case UART_SPEED2400: 100cc290419Sopenharmony_ci return (B2400); 101cc290419Sopenharmony_ci break; 102cc290419Sopenharmony_ci case UART_SPEED4800: 103cc290419Sopenharmony_ci return (B4800); 104cc290419Sopenharmony_ci break; 105cc290419Sopenharmony_ci case UART_SPEED9600: 106cc290419Sopenharmony_ci return (B9600); 107cc290419Sopenharmony_ci break; 108cc290419Sopenharmony_ci case UART_SPEED115200: 109cc290419Sopenharmony_ci return (B115200); 110cc290419Sopenharmony_ci break; 111cc290419Sopenharmony_ci case UART_SPEED921600: 112cc290419Sopenharmony_ci return (B921600); 113cc290419Sopenharmony_ci break; 114cc290419Sopenharmony_ci case UART_SPEED1500000: 115cc290419Sopenharmony_ci return (B1500000); 116cc290419Sopenharmony_ci default: 117cc290419Sopenharmony_ci return (B921600); 118cc290419Sopenharmony_ci break; 119cc290419Sopenharmony_ci } 120cc290419Sopenharmony_ci} 121cc290419Sopenharmony_ciint HdcUARTBase::GetUartBits(int bits) 122cc290419Sopenharmony_ci{ 123cc290419Sopenharmony_ci switch (bits) { 124cc290419Sopenharmony_ci case UART_BIT1: 125cc290419Sopenharmony_ci return (CS7); 126cc290419Sopenharmony_ci break; 127cc290419Sopenharmony_ci case UART_BIT2: 128cc290419Sopenharmony_ci return (CS8); 129cc290419Sopenharmony_ci break; 130cc290419Sopenharmony_ci default: 131cc290419Sopenharmony_ci return (CS8); 132cc290419Sopenharmony_ci break; 133cc290419Sopenharmony_ci } 134cc290419Sopenharmony_ci} 135cc290419Sopenharmony_ci#if defined(HOST_MAC) 136cc290419Sopenharmony_ciint HdcUARTBase::SetSerial(int fd, int nSpeed, int nBits, char nEvent, int nStop) 137cc290419Sopenharmony_ci{ 138cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "mac SetSerial rate = %d", nSpeed); 139cc290419Sopenharmony_ci struct termios options; 140cc290419Sopenharmony_ci struct termios oldttys1; 141cc290419Sopenharmony_ci if (tcgetattr(fd, &oldttys1) != 0) { 142cc290419Sopenharmony_ci constexpr int bufSize = 1024; 143cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 144cc290419Sopenharmony_ci strerror_r(errno, buf, bufSize); 145cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "tcgetattr failed with %s\n", buf); 146cc290419Sopenharmony_ci return ERR_GENERIC; 147cc290419Sopenharmony_ci } 148cc290419Sopenharmony_ci 149cc290419Sopenharmony_ci if (memcpy_s(&options, sizeof(options), &oldttys1, sizeof(options)) != EOK) { 150cc290419Sopenharmony_ci return ERR_GENERIC; 151cc290419Sopenharmony_ci } 152cc290419Sopenharmony_ci cfmakeraw(&options); 153cc290419Sopenharmony_ci options.c_cc[VMIN] = 0; 154cc290419Sopenharmony_ci options.c_cc[VTIME] = 10; // 10 * 1/10 sec : 1 sec 155cc290419Sopenharmony_ci 156cc290419Sopenharmony_ci cfsetspeed(&options, B19200); 157cc290419Sopenharmony_ci options.c_cflag |= GetUartBits(nBits); // Use 8 bit words 158cc290419Sopenharmony_ci options.c_cflag &= ~PARENB; 159cc290419Sopenharmony_ci 160cc290419Sopenharmony_ci speed_t speed = nSpeed; 161cc290419Sopenharmony_ci if (ioctl(fd, IOSSIOSPEED, &speed) == -1) { 162cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "set speed errno %d", errno); 163cc290419Sopenharmony_ci } 164cc290419Sopenharmony_ci if ((tcsetattr(fd, TCSANOW, &options)) != 0) { 165cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "com set error errno = %d", errno); 166cc290419Sopenharmony_ci return ERR_GENERIC; 167cc290419Sopenharmony_ci } 168cc290419Sopenharmony_ci if (ioctl(fd, IOSSIOSPEED, &speed) == -1) { 169cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "set speed errno %d", errno); 170cc290419Sopenharmony_ci } 171cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, " SetSerial OK rate = %d", nSpeed); 172cc290419Sopenharmony_ci return RET_SUCCESS; 173cc290419Sopenharmony_ci} 174cc290419Sopenharmony_ci#else 175cc290419Sopenharmony_ciint HdcUARTBase::SetSerial(int fd, int nSpeed, int nBits, char nEvent, int nStop) 176cc290419Sopenharmony_ci{ 177cc290419Sopenharmony_ci struct termios newttys1; 178cc290419Sopenharmony_ci struct termios oldttys1; 179cc290419Sopenharmony_ci if (tcgetattr(fd, &oldttys1) != 0) { 180cc290419Sopenharmony_ci constexpr int bufSize = 1024; 181cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 182cc290419Sopenharmony_ci strerror_r(errno, buf, bufSize); 183cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "tcgetattr failed with %s\n", buf); 184cc290419Sopenharmony_ci return ERR_GENERIC; 185cc290419Sopenharmony_ci } 186cc290419Sopenharmony_ci bzero(&newttys1, sizeof(newttys1)); 187cc290419Sopenharmony_ci newttys1.c_cflag = GetUartSpeed(nSpeed); 188cc290419Sopenharmony_ci newttys1.c_cflag |= (CLOCAL | CREAD); 189cc290419Sopenharmony_ci newttys1.c_cflag &= ~CSIZE; 190cc290419Sopenharmony_ci newttys1.c_lflag &= ~ICANON; 191cc290419Sopenharmony_ci newttys1.c_cflag |= GetUartBits(nBits); 192cc290419Sopenharmony_ci switch (nEvent) { 193cc290419Sopenharmony_ci case 'O': 194cc290419Sopenharmony_ci newttys1.c_cflag |= PARENB; 195cc290419Sopenharmony_ci newttys1.c_iflag |= (INPCK | ISTRIP); 196cc290419Sopenharmony_ci newttys1.c_cflag |= PARODD; 197cc290419Sopenharmony_ci break; 198cc290419Sopenharmony_ci case 'E': 199cc290419Sopenharmony_ci newttys1.c_cflag |= PARENB; 200cc290419Sopenharmony_ci newttys1.c_iflag |= (INPCK | ISTRIP); 201cc290419Sopenharmony_ci newttys1.c_cflag &= ~PARODD; 202cc290419Sopenharmony_ci break; 203cc290419Sopenharmony_ci case 'N': 204cc290419Sopenharmony_ci newttys1.c_cflag &= ~PARENB; 205cc290419Sopenharmony_ci break; 206cc290419Sopenharmony_ci default: 207cc290419Sopenharmony_ci break; 208cc290419Sopenharmony_ci } 209cc290419Sopenharmony_ci if (nStop == UART_STOP1) { 210cc290419Sopenharmony_ci newttys1.c_cflag &= ~CSTOPB; 211cc290419Sopenharmony_ci } else if (nStop == UART_STOP2) { 212cc290419Sopenharmony_ci newttys1.c_cflag |= CSTOPB; 213cc290419Sopenharmony_ci } 214cc290419Sopenharmony_ci newttys1.c_cc[VTIME] = 0; 215cc290419Sopenharmony_ci newttys1.c_cc[VMIN] = 0; 216cc290419Sopenharmony_ci if (tcflush(fd, TCIOFLUSH)) { 217cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, " tcflush error."); 218cc290419Sopenharmony_ci return ERR_GENERIC; 219cc290419Sopenharmony_ci } 220cc290419Sopenharmony_ci if ((tcsetattr(fd, TCSANOW, &newttys1)) != 0) { 221cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "com set error errno = %d", errno); 222cc290419Sopenharmony_ci return ERR_GENERIC; 223cc290419Sopenharmony_ci } 224cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, " SetSerial OK rate = %d", nSpeed); 225cc290419Sopenharmony_ci return RET_SUCCESS; 226cc290419Sopenharmony_ci} 227cc290419Sopenharmony_ci#endif 228cc290419Sopenharmony_ci#endif // _WIN32 229cc290419Sopenharmony_ci 230cc290419Sopenharmony_cissize_t HdcUARTBase::ReadUartDev(std::vector<uint8_t> &readBuf, size_t expectedSize, HdcUART &uart) 231cc290419Sopenharmony_ci{ 232cc290419Sopenharmony_ci ssize_t totalBytesRead = 0; 233cc290419Sopenharmony_ci uint8_t uartReadBuffer[MAX_UART_SIZE_IOBUF]; 234cc290419Sopenharmony_ci#ifdef _WIN32 235cc290419Sopenharmony_ci DWORD bytesRead = 0; 236cc290419Sopenharmony_ci#else 237cc290419Sopenharmony_ci ssize_t bytesRead = 0; 238cc290419Sopenharmony_ci#endif 239cc290419Sopenharmony_ci do { 240cc290419Sopenharmony_ci bytesRead = 0; 241cc290419Sopenharmony_ci#ifdef _WIN32 242cc290419Sopenharmony_ci BOOL bReadStatus = ReadFile(uart.devUartHandle, uartReadBuffer, sizeof(uartReadBuffer), 243cc290419Sopenharmony_ci &bytesRead, &uart.ovRead); 244cc290419Sopenharmony_ci if (!bReadStatus) { 245cc290419Sopenharmony_ci if (GetLastError() == ERROR_IO_PENDING) { 246cc290419Sopenharmony_ci bytesRead = 0; 247cc290419Sopenharmony_ci DWORD dwMilliseconds = READ_GIVE_UP_TIME_OUT_TIME_MS; 248cc290419Sopenharmony_ci if (expectedSize == 0) { 249cc290419Sopenharmony_ci dwMilliseconds = INFINITE; 250cc290419Sopenharmony_ci } 251cc290419Sopenharmony_ci if (!GetOverlappedResultEx(uart.devUartHandle, &uart.ovRead, &bytesRead, 252cc290419Sopenharmony_ci dwMilliseconds, FALSE)) { 253cc290419Sopenharmony_ci // wait io failed 254cc290419Sopenharmony_ci DWORD error = GetLastError(); 255cc290419Sopenharmony_ci if (error == ERROR_OPERATION_ABORTED) { 256cc290419Sopenharmony_ci totalBytesRead += bytesRead; 257cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s error cancel read. %u %zd", __FUNCTION__, 258cc290419Sopenharmony_ci bytesRead, totalBytesRead); 259cc290419Sopenharmony_ci // Generally speaking, this is the cacnel caused by freesession 260cc290419Sopenharmony_ci // Returning allows the outer read loop to run again. This checks the exit 261cc290419Sopenharmony_ci // condition. 262cc290419Sopenharmony_ci return totalBytesRead; 263cc290419Sopenharmony_ci } else if (error == WAIT_TIMEOUT) { 264cc290419Sopenharmony_ci totalBytesRead += bytesRead; 265cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s error timeout. %u %zd", __FUNCTION__, bytesRead, 266cc290419Sopenharmony_ci totalBytesRead); 267cc290419Sopenharmony_ci return totalBytesRead; 268cc290419Sopenharmony_ci } else { 269cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s error wait io:%d.", __FUNCTION__, GetLastError()); 270cc290419Sopenharmony_ci } 271cc290419Sopenharmony_ci return -1; 272cc290419Sopenharmony_ci } 273cc290419Sopenharmony_ci } else { 274cc290419Sopenharmony_ci // not ERROR_IO_PENDING 275cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s err:%d. ", __FUNCTION__, GetLastError()); 276cc290419Sopenharmony_ci return -1; 277cc290419Sopenharmony_ci } 278cc290419Sopenharmony_ci } 279cc290419Sopenharmony_ci#else 280cc290419Sopenharmony_ci int ret = 0; 281cc290419Sopenharmony_ci fd_set readFds; 282cc290419Sopenharmony_ci FD_ZERO(&readFds); 283cc290419Sopenharmony_ci FD_SET(uart.devUartHandle, &readFds); 284cc290419Sopenharmony_ci const constexpr int msTous = 1000; 285cc290419Sopenharmony_ci const constexpr int sTous = 1000 * msTous; 286cc290419Sopenharmony_ci struct timeval tv; 287cc290419Sopenharmony_ci tv.tv_sec = 0; 288cc290419Sopenharmony_ci 289cc290419Sopenharmony_ci if (expectedSize == 0) { 290cc290419Sopenharmony_ci tv.tv_usec = WAIT_RESPONSE_TIME_OUT_MS * msTous; 291cc290419Sopenharmony_ci tv.tv_sec = tv.tv_usec / sTous; 292cc290419Sopenharmony_ci tv.tv_usec = tv.tv_usec % sTous; 293cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "time = %d %d", tv.tv_sec, tv.tv_sec); 294cc290419Sopenharmony_ci#ifdef HDC_HOST 295cc290419Sopenharmony_ci // only host side need this 296cc290419Sopenharmony_ci // in this caes 297cc290419Sopenharmony_ci // We need a way to exit from the select for the destruction and recovery of the 298cc290419Sopenharmony_ci // serial port read thread. 299cc290419Sopenharmony_ci ret = select(uart.devUartHandle + 1, &readFds, nullptr, nullptr, &tv); 300cc290419Sopenharmony_ci#else 301cc290419Sopenharmony_ci ret = select(uart.devUartHandle + 1, &readFds, nullptr, nullptr, nullptr); 302cc290419Sopenharmony_ci#endif 303cc290419Sopenharmony_ci } else { 304cc290419Sopenharmony_ci // when we have expect size , we need timeout for link data drop issue 305cc290419Sopenharmony_ci tv.tv_usec = READ_GIVE_UP_TIME_OUT_TIME_MS * msTous; 306cc290419Sopenharmony_ci tv.tv_sec = tv.tv_usec / sTous; 307cc290419Sopenharmony_ci tv.tv_usec = tv.tv_usec % sTous; 308cc290419Sopenharmony_ci ret = select(uart.devUartHandle + 1, &readFds, nullptr, nullptr, &tv); 309cc290419Sopenharmony_ci } 310cc290419Sopenharmony_ci if (ret == 0 and expectedSize == 0) { 311cc290419Sopenharmony_ci // no expect but timeout 312cc290419Sopenharmony_ci if (uart.ioCancel) { 313cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s:uart select time out and io cancel", __FUNCTION__); 314cc290419Sopenharmony_ci uart.ioCancel = true; 315cc290419Sopenharmony_ci return totalBytesRead; 316cc290419Sopenharmony_ci } else { 317cc290419Sopenharmony_ci continue; 318cc290419Sopenharmony_ci } 319cc290419Sopenharmony_ci } else if (ret == 0) { 320cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s:uart select time out!", __FUNCTION__); 321cc290419Sopenharmony_ci // we expected some byte , but not arrive before timeout 322cc290419Sopenharmony_ci return totalBytesRead; 323cc290419Sopenharmony_ci } else if (ret < 0) { 324cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s:uart select error! %d", __FUNCTION__, errno); 325cc290419Sopenharmony_ci return -1; // wait failed. 326cc290419Sopenharmony_ci } else { 327cc290419Sopenharmony_ci // select > 0 328cc290419Sopenharmony_ci bytesRead = read(uart.devUartHandle, uartReadBuffer, sizeof(uartReadBuffer)); 329cc290419Sopenharmony_ci if (bytesRead <= 0) { 330cc290419Sopenharmony_ci // read failed ! 331cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s:read failed! %zd:%d", __FUNCTION__, bytesRead, errno); 332cc290419Sopenharmony_ci return -1; 333cc290419Sopenharmony_ci } 334cc290419Sopenharmony_ci } 335cc290419Sopenharmony_ci#endif 336cc290419Sopenharmony_ci if (bytesRead > 0) { 337cc290419Sopenharmony_ci readBuf.insert(readBuf.end(), uartReadBuffer, uartReadBuffer + bytesRead); 338cc290419Sopenharmony_ci totalBytesRead += bytesRead; 339cc290419Sopenharmony_ci } 340cc290419Sopenharmony_ci } while (readBuf.size() < expectedSize or 341cc290419Sopenharmony_ci bytesRead == 0); // if caller know how many bytes it want 342cc290419Sopenharmony_ci return totalBytesRead; 343cc290419Sopenharmony_ci} 344cc290419Sopenharmony_ci 345cc290419Sopenharmony_cissize_t HdcUARTBase::WriteUartDev(uint8_t *data, const size_t length, HdcUART &uart) 346cc290419Sopenharmony_ci{ 347cc290419Sopenharmony_ci ssize_t totalBytesWrite = 0; 348cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "%s %d data %x %x", __FUNCTION__, length, *(data + sizeof(UartHead)), 349cc290419Sopenharmony_ci *(data + sizeof(UartHead) + 1)); 350cc290419Sopenharmony_ci do { 351cc290419Sopenharmony_ci#ifdef _WIN32 352cc290419Sopenharmony_ci DWORD bytesWrite = 0; 353cc290419Sopenharmony_ci BOOL bWriteStat = WriteFile(uart.devUartHandle, data + totalBytesWrite, 354cc290419Sopenharmony_ci length - totalBytesWrite, &bytesWrite, &uart.ovWrite); 355cc290419Sopenharmony_ci if (!bWriteStat) { 356cc290419Sopenharmony_ci if (GetLastError() == ERROR_IO_PENDING) { 357cc290419Sopenharmony_ci if (!GetOverlappedResult(uart.devUartHandle, &uart.ovWrite, &bytesWrite, TRUE)) { 358cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s error wait io:%d. bytesWrite %zu", __FUNCTION__, 359cc290419Sopenharmony_ci GetLastError(), bytesWrite); 360cc290419Sopenharmony_ci return -1; 361cc290419Sopenharmony_ci } 362cc290419Sopenharmony_ci } else { 363cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s err:%d. bytesWrite %zu", __FUNCTION__, GetLastError(), 364cc290419Sopenharmony_ci bytesWrite); 365cc290419Sopenharmony_ci return -1; 366cc290419Sopenharmony_ci } 367cc290419Sopenharmony_ci } 368cc290419Sopenharmony_ci#else // not win32 369cc290419Sopenharmony_ci ssize_t bytesWrite = 0; 370cc290419Sopenharmony_ci bytesWrite = write(uart.devUartHandle, data + totalBytesWrite, length - totalBytesWrite); 371cc290419Sopenharmony_ci if (bytesWrite < 0) { 372cc290419Sopenharmony_ci if (errno == EINTR or errno == EAGAIN) { 373cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "EINTR/EAGAIN, try again"); 374cc290419Sopenharmony_ci continue; 375cc290419Sopenharmony_ci } else { 376cc290419Sopenharmony_ci // we don't know how to recory in this function 377cc290419Sopenharmony_ci // need reopen device ? 378cc290419Sopenharmony_ci constexpr int bufSize = 1024; 379cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 380cc290419Sopenharmony_ci strerror_r(errno, buf, bufSize); 381cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "write fatal errno %d:%s", errno, buf); 382cc290419Sopenharmony_ci return -1; 383cc290419Sopenharmony_ci } 384cc290419Sopenharmony_ci } else { 385cc290419Sopenharmony_ci // waits until all output written to the object referred to by fd has been transmitted. 386cc290419Sopenharmony_ci tcdrain(uart.devUartHandle); 387cc290419Sopenharmony_ci } 388cc290419Sopenharmony_ci#endif 389cc290419Sopenharmony_ci totalBytesWrite += bytesWrite; 390cc290419Sopenharmony_ci } while (totalBytesWrite < signed(length)); 391cc290419Sopenharmony_ci 392cc290419Sopenharmony_ci return totalBytesWrite; 393cc290419Sopenharmony_ci} 394cc290419Sopenharmony_ci 395cc290419Sopenharmony_ciint HdcUARTBase::UartToHdcProtocol(uv_stream_t *stream, uint8_t *data, int dataSize) 396cc290419Sopenharmony_ci{ 397cc290419Sopenharmony_ci HSession hSession = (HSession)stream->data; 398cc290419Sopenharmony_ci unsigned int fd = hSession->dataFd[STREAM_MAIN]; 399cc290419Sopenharmony_ci fd_set fdSet; 400cc290419Sopenharmony_ci struct timeval timeout = {3, 0}; 401cc290419Sopenharmony_ci FD_ZERO(&fdSet); 402cc290419Sopenharmony_ci FD_SET(fd, &fdSet); 403cc290419Sopenharmony_ci int index = 0; 404cc290419Sopenharmony_ci int childRet = 0; 405cc290419Sopenharmony_ci 406cc290419Sopenharmony_ci while (index < dataSize) { 407cc290419Sopenharmony_ci childRet = select(fd + 1, NULL, &fdSet, NULL, &timeout); 408cc290419Sopenharmony_ci if (childRet <= 0) { 409cc290419Sopenharmony_ci constexpr int bufSize = 1024; 410cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 411cc290419Sopenharmony_ci#ifdef _WIN32 412cc290419Sopenharmony_ci strerror_s(buf, bufSize, errno); 413cc290419Sopenharmony_ci#else 414cc290419Sopenharmony_ci strerror_r(errno, buf, bufSize); 415cc290419Sopenharmony_ci#endif 416cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s select error:%d [%s][%d]", __FUNCTION__, errno, 417cc290419Sopenharmony_ci buf, childRet); 418cc290419Sopenharmony_ci break; 419cc290419Sopenharmony_ci } 420cc290419Sopenharmony_ci childRet = send(fd, (const char *)data + index, dataSize - index, 0); 421cc290419Sopenharmony_ci if (childRet < 0) { 422cc290419Sopenharmony_ci constexpr int bufSize = 1024; 423cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 424cc290419Sopenharmony_ci#ifdef _WIN32 425cc290419Sopenharmony_ci strerror_s(buf, bufSize, errno); 426cc290419Sopenharmony_ci#else 427cc290419Sopenharmony_ci strerror_r(errno, buf, bufSize); 428cc290419Sopenharmony_ci#endif 429cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s senddata err:%d [%s]", __FUNCTION__, errno, buf); 430cc290419Sopenharmony_ci break; 431cc290419Sopenharmony_ci } 432cc290419Sopenharmony_ci index += childRet; 433cc290419Sopenharmony_ci } 434cc290419Sopenharmony_ci if (index != dataSize) { 435cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s partialsenddata err:%d [%d]", __FUNCTION__, index, dataSize); 436cc290419Sopenharmony_ci return ERR_IO_FAIL; 437cc290419Sopenharmony_ci } 438cc290419Sopenharmony_ci return index; 439cc290419Sopenharmony_ci} 440cc290419Sopenharmony_ci 441cc290419Sopenharmony_ciRetErrCode HdcUARTBase::DispatchToWorkThread(HSession hSession, uint8_t *readBuf, int readBytes) 442cc290419Sopenharmony_ci{ 443cc290419Sopenharmony_ci if (hSession == nullptr) { 444cc290419Sopenharmony_ci return ERR_SESSION_NOFOUND; 445cc290419Sopenharmony_ci } 446cc290419Sopenharmony_ci if (!UartSendToHdcStream(hSession, readBuf, readBytes)) { 447cc290419Sopenharmony_ci return ERR_IO_FAIL; 448cc290419Sopenharmony_ci } 449cc290419Sopenharmony_ci return RET_SUCCESS; 450cc290419Sopenharmony_ci} 451cc290419Sopenharmony_ci 452cc290419Sopenharmony_cisize_t HdcUARTBase::PackageProcess(vector<uint8_t> &data, HSession hSession) 453cc290419Sopenharmony_ci{ 454cc290419Sopenharmony_ci while (data.size() >= sizeof(UartHead)) { 455cc290419Sopenharmony_ci // is size more than one head 456cc290419Sopenharmony_ci size_t packetSize = 0; 457cc290419Sopenharmony_ci uint32_t sessionId = 0; 458cc290419Sopenharmony_ci uint32_t packageIndex = 0; 459cc290419Sopenharmony_ci // we erase all buffer. wait next read. 460cc290419Sopenharmony_ci if (ValidateUartPacket(data, sessionId, packageIndex, packetSize) != RET_SUCCESS) { 461cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s package error. clean the read buffer.", __FUNCTION__); 462cc290419Sopenharmony_ci data.clear(); 463cc290419Sopenharmony_ci } else if (packetSize == sizeof(UartHead)) { 464cc290419Sopenharmony_ci // nothing need to send, this is a head only package 465cc290419Sopenharmony_ci // only used in link layer 466cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "%s headonly Package(%zu). dont send to session, erase it", 467cc290419Sopenharmony_ci __FUNCTION__, packetSize); 468cc290419Sopenharmony_ci } else { 469cc290419Sopenharmony_ci // at least we got one package 470cc290419Sopenharmony_ci // if the size of package have all received ? 471cc290419Sopenharmony_ci if (data.size() >= packetSize) { 472cc290419Sopenharmony_ci // send the data to logic level (link to logic) 473cc290419Sopenharmony_ci if (hSession == nullptr) { 474cc290419Sopenharmony_ci#ifdef HDC_HOST 475cc290419Sopenharmony_ci hSession = GetSession(sessionId); 476cc290419Sopenharmony_ci#else 477cc290419Sopenharmony_ci // for daemon side we can make a new session for it 478cc290419Sopenharmony_ci hSession = GetSession(sessionId, true); 479cc290419Sopenharmony_ci#endif 480cc290419Sopenharmony_ci } 481cc290419Sopenharmony_ci if (hSession == nullptr) { 482cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s have not found session (%u). skip it", __FUNCTION__, sessionId); 483cc290419Sopenharmony_ci } else { 484cc290419Sopenharmony_ci if (hSession->hUART->dispatchedPackageIndex == packageIndex) { 485cc290419Sopenharmony_ci // we need check if the duplication package we have already send 486cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s dup package %u, skip send to session logic", 487cc290419Sopenharmony_ci __FUNCTION__, packageIndex); 488cc290419Sopenharmony_ci } else { 489cc290419Sopenharmony_ci // update the last package we will send to hdc 490cc290419Sopenharmony_ci hSession->hUART->dispatchedPackageIndex = packageIndex; 491cc290419Sopenharmony_ci RetErrCode ret = DispatchToWorkThread(hSession, data.data(), packetSize); 492cc290419Sopenharmony_ci if (ret == RET_SUCCESS) { 493cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s DispatchToWorkThread successful", 494cc290419Sopenharmony_ci __FUNCTION__); 495cc290419Sopenharmony_ci } else { 496cc290419Sopenharmony_ci // send to logic failed. 497cc290419Sopenharmony_ci // this kind of issue unable handle in link layer 498cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, 499cc290419Sopenharmony_ci "%s DispatchToWorkThread fail %d. request free session in " 500cc290419Sopenharmony_ci "other side", 501cc290419Sopenharmony_ci __FUNCTION__, ret); 502cc290419Sopenharmony_ci ResponseUartTrans(hSession->sessionId, ++hSession->hUART->packageIndex, 503cc290419Sopenharmony_ci PKG_OPTION_FREE); 504cc290419Sopenharmony_ci } 505cc290419Sopenharmony_ci } 506cc290419Sopenharmony_ci } 507cc290419Sopenharmony_ci } else { 508cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s valid package, however size not enough. expect %zu", 509cc290419Sopenharmony_ci __FUNCTION__, packetSize); 510cc290419Sopenharmony_ci return packetSize; 511cc290419Sopenharmony_ci } 512cc290419Sopenharmony_ci } 513cc290419Sopenharmony_ci 514cc290419Sopenharmony_ci if (data.size() >= packetSize) { 515cc290419Sopenharmony_ci data.erase(data.begin(), data.begin() + packetSize); 516cc290419Sopenharmony_ci } else { 517cc290419Sopenharmony_ci // dont clean , should merge with next package 518cc290419Sopenharmony_ci } 519cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "PackageProcess data.size():%d left", data.size()); 520cc290419Sopenharmony_ci } 521cc290419Sopenharmony_ci // if we have at least one byte, we think there should be a head 522cc290419Sopenharmony_ci return data.size() > 1 ? sizeof(UartHead) : 0; 523cc290419Sopenharmony_ci} 524cc290419Sopenharmony_ci 525cc290419Sopenharmony_cibool HdcUARTBase::SendUARTRaw(HSession hSession, uint8_t *data, const size_t length) 526cc290419Sopenharmony_ci{ 527cc290419Sopenharmony_ci struct UartHead *uartHeader = (struct UartHead *)data; 528cc290419Sopenharmony_ci#ifndef HDC_HOST 529cc290419Sopenharmony_ci // review nobody can plug out the daemon uart , if we still need split write in daemon side? 530cc290419Sopenharmony_ci HdcUART deamonUart; 531cc290419Sopenharmony_ci deamonUart.devUartHandle = uartHandle; 532cc290419Sopenharmony_ci if (uartHeader->IsResponsePackage()) { 533cc290419Sopenharmony_ci // for the response package and in daemon side, 534cc290419Sopenharmony_ci // we dont need session info 535cc290419Sopenharmony_ci ssize_t sendBytes = WriteUartDev(data, length, deamonUart); 536cc290419Sopenharmony_ci return sendBytes > 0; 537cc290419Sopenharmony_ci } 538cc290419Sopenharmony_ci#endif 539cc290419Sopenharmony_ci 540cc290419Sopenharmony_ci // for normal package 541cc290419Sopenharmony_ci if (hSession == nullptr) { 542cc290419Sopenharmony_ci hSession = GetSession(uartHeader->sessionId); 543cc290419Sopenharmony_ci if (hSession == nullptr) { 544cc290419Sopenharmony_ci // session is not found 545cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s hSession not found:%zu", __FUNCTION__, uartHeader->sessionId); 546cc290419Sopenharmony_ci return false; 547cc290419Sopenharmony_ci } 548cc290419Sopenharmony_ci } 549cc290419Sopenharmony_ci hSession->ref++; 550cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s length:%d", __FUNCTION__, length); 551cc290419Sopenharmony_ci#ifdef HDC_HOST 552cc290419Sopenharmony_ci ssize_t sendBytes = WriteUartDev(data, length, *hSession->hUART); 553cc290419Sopenharmony_ci#else 554cc290419Sopenharmony_ci ssize_t sendBytes = WriteUartDev(data, length, deamonUart); 555cc290419Sopenharmony_ci#endif 556cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s sendBytes %zu", __FUNCTION__, sendBytes); 557cc290419Sopenharmony_ci if (sendBytes < 0) { 558cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s send fail. try to freesession", __FUNCTION__); 559cc290419Sopenharmony_ci OnTransferError(hSession); 560cc290419Sopenharmony_ci } 561cc290419Sopenharmony_ci hSession->ref--; 562cc290419Sopenharmony_ci return sendBytes > 0; 563cc290419Sopenharmony_ci} 564cc290419Sopenharmony_ci 565cc290419Sopenharmony_ci// this function will not check the data correct again 566cc290419Sopenharmony_ci// just send the data to hdc session side 567cc290419Sopenharmony_cibool HdcUARTBase::UartSendToHdcStream(HSession hSession, uint8_t *data, size_t size) 568cc290419Sopenharmony_ci{ 569cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s send to session %s package size %zu", __FUNCTION__, 570cc290419Sopenharmony_ci hSession->ToDebugString().c_str(), size); 571cc290419Sopenharmony_ci 572cc290419Sopenharmony_ci int ret = RET_SUCCESS; 573cc290419Sopenharmony_ci 574cc290419Sopenharmony_ci if (size < sizeof(UartHead)) { 575cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s buf size too small %zu", __FUNCTION__, size); 576cc290419Sopenharmony_ci return ERR_BUF_SIZE; 577cc290419Sopenharmony_ci } 578cc290419Sopenharmony_ci 579cc290419Sopenharmony_ci UartHead *head = reinterpret_cast<UartHead *>(data); 580cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s uartHeader:%s data: %x %x", __FUNCTION__, 581cc290419Sopenharmony_ci head->ToDebugString().c_str(), *(data + sizeof(UartHead)), 582cc290419Sopenharmony_ci *(data + sizeof(UartHead) + 1)); 583cc290419Sopenharmony_ci 584cc290419Sopenharmony_ci // review need check logic again here or err process 585cc290419Sopenharmony_ci if (head->sessionId != hSession->sessionId) { 586cc290419Sopenharmony_ci if (hSession->serverOrDaemon && !hSession->hUART->resetIO) { 587cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s sessionId not matched, reset sessionId:%d.", __FUNCTION__, 588cc290419Sopenharmony_ci head->sessionId); 589cc290419Sopenharmony_ci SendUartSoftReset(hSession, head->sessionId); 590cc290419Sopenharmony_ci hSession->hUART->resetIO = true; 591cc290419Sopenharmony_ci ret = ERR_IO_SOFT_RESET; 592cc290419Sopenharmony_ci // dont break ,we need rease these data in recv buffer 593cc290419Sopenharmony_ci } 594cc290419Sopenharmony_ci } else { 595cc290419Sopenharmony_ci // data to session 596cc290419Sopenharmony_ci hSession->hUART->streamSize += head->dataSize; // this is only for debug, 597cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "%s stream wait session read size: %zu", __FUNCTION__, 598cc290419Sopenharmony_ci hSession->hUART->streamSize.load()); 599cc290419Sopenharmony_ci if (UartToHdcProtocol(reinterpret_cast<uv_stream_t *>(&hSession->dataPipe[STREAM_MAIN]), 600cc290419Sopenharmony_ci data + sizeof(UartHead), head->dataSize) < 0) { 601cc290419Sopenharmony_ci ret = ERR_IO_FAIL; 602cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s Error uart send to stream", __FUNCTION__); 603cc290419Sopenharmony_ci } 604cc290419Sopenharmony_ci } 605cc290419Sopenharmony_ci 606cc290419Sopenharmony_ci return ret == RET_SUCCESS; 607cc290419Sopenharmony_ci} 608cc290419Sopenharmony_ci 609cc290419Sopenharmony_civoid HdcUARTBase::NotifyTransfer() 610cc290419Sopenharmony_ci{ 611cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s", __FUNCTION__); 612cc290419Sopenharmony_ci transfer.Request(); 613cc290419Sopenharmony_ci} 614cc290419Sopenharmony_ci 615cc290419Sopenharmony_ci/* 616cc290419Sopenharmony_cihere we have a HandleOutputPkg vector 617cc290419Sopenharmony_ciIt is used to maintain the data reliability of the link layer 618cc290419Sopenharmony_ciIt consists of the following part 619cc290419Sopenharmony_ciLog data to send (caller thread) --> RequestSendPackage 620cc290419Sopenharmony_ciSend recorded data (loop sending thread) --> SendPkgInUARTOutMap 621cc290419Sopenharmony_ciProcess the returned reply data (loop reading thread) --> ProcessResponsePackage 622cc290419Sopenharmony_ciSend reply packet (loop reading thread) --> ResponseUartTrans 623cc290419Sopenharmony_ci 624cc290419Sopenharmony_ciThe key scenarios are as follows: 625cc290419Sopenharmony_ciPackage is sent from side A to side B 626cc290419Sopenharmony_ciHere we call the complete data package 627cc290419Sopenharmony_cipackage is divided into head and data 628cc290419Sopenharmony_ciThe response information is in the header. 629cc290419Sopenharmony_cidata contains binary data. 630cc290419Sopenharmony_ci 631cc290419Sopenharmony_cicase 1: Normal Process 632cc290419Sopenharmony_ci package 633cc290419Sopenharmony_ciA --> B 634cc290419Sopenharmony_ci ACK 635cc290419Sopenharmony_ciA <-- B 636cc290419Sopenharmony_ci 637cc290419Sopenharmony_cicase 2: packet is incorrect 638cc290419Sopenharmony_ciAt least one header must be received 639cc290419Sopenharmony_ciFor this the B side needs to have an accept timeout. 640cc290419Sopenharmony_ciThere is no new data within a certain period of time as the end of the packet. 641cc290419Sopenharmony_ci(This mechanism is not handled in HandleOutputPkg retransmission) 642cc290419Sopenharmony_ci 643cc290419Sopenharmony_ci incorrect 644cc290419Sopenharmony_ciA --> B 645cc290419Sopenharmony_ciB sends NAK and A resends the packet. 646cc290419Sopenharmony_ci NAK 647cc290419Sopenharmony_ciA <-- B 648cc290419Sopenharmony_ci package resend 649cc290419Sopenharmony_ciA --> B 650cc290419Sopenharmony_ci 651cc290419Sopenharmony_cicase 3: packet is complete lost() 652cc290419Sopenharmony_ci package(complete lost) 653cc290419Sopenharmony_ciA -x-> B 654cc290419Sopenharmony_ciThe A side needs to resend the Package after a certain timeout 655cc290419Sopenharmony_ciA --> B 656cc290419Sopenharmony_ciUntil the B side has a data report (ACK or NAK), or the number of retransmissions reaches the upper 657cc290419Sopenharmony_cilimit. 658cc290419Sopenharmony_ci*/ 659cc290419Sopenharmony_civoid HdcUARTBase::RequestSendPackage(uint8_t *data, const size_t length, bool queue) 660cc290419Sopenharmony_ci{ 661cc290419Sopenharmony_ci UartHead *head = reinterpret_cast<UartHead *>(data); 662cc290419Sopenharmony_ci bool response = head->IsResponsePackage(); 663cc290419Sopenharmony_ci 664cc290419Sopenharmony_ci if (queue) { 665cc290419Sopenharmony_ci slots.Wait(head->sessionId); 666cc290419Sopenharmony_ci } 667cc290419Sopenharmony_ci 668cc290419Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(mapOutPkgsMutex); 669cc290419Sopenharmony_ci 670cc290419Sopenharmony_ci std::string pkgId = head->ToPkgIdentityString(response); 671cc290419Sopenharmony_ci auto it = std::find_if(outPkgs.begin(), outPkgs.end(), HandleOutputPkgKeyFinder(pkgId)); 672cc290419Sopenharmony_ci if (it == outPkgs.end()) { 673cc290419Sopenharmony_ci // update che checksum , both head and data 674cc290419Sopenharmony_ci head->UpdateCheckSum(); 675cc290419Sopenharmony_ci outPkgs.emplace_back(pkgId, head->sessionId, data, length, response, 676cc290419Sopenharmony_ci head->option & PKG_OPTION_ACK); 677cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: add pkg %s (pkgs size %zu)", 678cc290419Sopenharmony_ci head->ToDebugString().c_str(), outPkgs.size()); 679cc290419Sopenharmony_ci } else { 680cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "UartPackageManager: add pkg %s fail, %s has already been exist.", 681cc290419Sopenharmony_ci head->ToDebugString().c_str(), pkgId.c_str()); 682cc290419Sopenharmony_ci } 683cc290419Sopenharmony_ci NotifyTransfer(); 684cc290419Sopenharmony_ci} 685cc290419Sopenharmony_ci 686cc290419Sopenharmony_civoid HdcUARTBase::ProcessResponsePackage(const UartHead &head) 687cc290419Sopenharmony_ci{ 688cc290419Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(mapOutPkgsMutex); 689cc290419Sopenharmony_ci bool ack = head.option & PKG_OPTION_ACK; 690cc290419Sopenharmony_ci // response package 691cc290419Sopenharmony_ci std::string pkgId = head.ToPkgIdentityString(); 692cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "UartPackageManager: got response pkgId:%s ack:%d.", pkgId.c_str(), ack); 693cc290419Sopenharmony_ci 694cc290419Sopenharmony_ci auto it = std::find_if(outPkgs.begin(), outPkgs.end(), HandleOutputPkgKeyFinder(pkgId)); 695cc290419Sopenharmony_ci if (it != outPkgs.end()) { 696cc290419Sopenharmony_ci if (ack) { // response ACK. 697cc290419Sopenharmony_ci slots.Free(it->sessionId); 698cc290419Sopenharmony_ci outPkgs.erase(it); 699cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: erase pkgId:%s.", pkgId.c_str()); 700cc290419Sopenharmony_ci } else { // response NAK 701cc290419Sopenharmony_ci it->pkgStatus = PKG_WAIT_SEND; // Re send the pkg 702cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UartPackageManager: resend pkgId:%s.", pkgId.c_str()); 703cc290419Sopenharmony_ci } 704cc290419Sopenharmony_ci } else { 705cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "UartPackageManager: hasn't found pkg for pkgId:%s.", pkgId.c_str()); 706cc290419Sopenharmony_ci for (auto pkg : outPkgs) { 707cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "UartPackageManager: pkgId:%s.", pkg.key.c_str()); 708cc290419Sopenharmony_ci } 709cc290419Sopenharmony_ci } 710cc290419Sopenharmony_ci NotifyTransfer(); 711cc290419Sopenharmony_ci return; 712cc290419Sopenharmony_ci} 713cc290419Sopenharmony_ci 714cc290419Sopenharmony_civoid HdcUARTBase::SendPkgInUARTOutMap() 715cc290419Sopenharmony_ci{ 716cc290419Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(mapOutPkgsMutex); 717cc290419Sopenharmony_ci if (outPkgs.empty()) { 718cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "UartPackageManager: No pkgs needs to be sent."); 719cc290419Sopenharmony_ci return; 720cc290419Sopenharmony_ci } 721cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: send pkgs, have:%zu pkgs", outPkgs.size()); 722cc290419Sopenharmony_ci // we have maybe more than one session 723cc290419Sopenharmony_ci // each session has it owner serial port 724cc290419Sopenharmony_ci std::unordered_set<uint32_t> hasWaitPkg; 725cc290419Sopenharmony_ci auto it = outPkgs.begin(); 726cc290419Sopenharmony_ci while (it != outPkgs.end()) { 727cc290419Sopenharmony_ci if (it->pkgStatus == PKG_WAIT_SEND) { 728cc290419Sopenharmony_ci // we found a pkg wait for send 729cc290419Sopenharmony_ci // if a response package 730cc290419Sopenharmony_ci // response package always send nowait noorder 731cc290419Sopenharmony_ci if (!it->response and hasWaitPkg.find(it->sessionId) != hasWaitPkg.end()) { 732cc290419Sopenharmony_ci // this is not a response package 733cc290419Sopenharmony_ci // and this session is wait response 734cc290419Sopenharmony_ci // so we can send nothing 735cc290419Sopenharmony_ci // process next 736cc290419Sopenharmony_ci it++; 737cc290419Sopenharmony_ci continue; 738cc290419Sopenharmony_ci } 739cc290419Sopenharmony_ci // we will ready to send the package 740cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: send pkg %s", it->ToDebugString().c_str()); 741cc290419Sopenharmony_ci if (!SendUARTRaw(nullptr, it->msgSendBuf.data(), it->msgSendBuf.size())) { 742cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendUARTRaw failed!"); 743cc290419Sopenharmony_ci break; 744cc290419Sopenharmony_ci } 745cc290419Sopenharmony_ci if (it->response) { 746cc290419Sopenharmony_ci // response pkg dont need wait response again. 747cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: erase pkg %s", 748cc290419Sopenharmony_ci it->ToDebugString().c_str()); 749cc290419Sopenharmony_ci it = outPkgs.erase(it); 750cc290419Sopenharmony_ci continue; 751cc290419Sopenharmony_ci } else { 752cc290419Sopenharmony_ci // normal send package 753cc290419Sopenharmony_ci it->pkgStatus = PKG_WAIT_RESPONSE; 754cc290419Sopenharmony_ci it->sendTimePoint = steady_clock::now(); 755cc290419Sopenharmony_ci hasWaitPkg.emplace(it->sessionId); 756cc290419Sopenharmony_ci transfer.Sent(); // something is sendout, transfer will timeout for next wait. 757cc290419Sopenharmony_ci } 758cc290419Sopenharmony_ci } else if (it->pkgStatus == PKG_WAIT_RESPONSE) { 759cc290419Sopenharmony_ci // we found a pkg wait for response 760cc290419Sopenharmony_ci auto elapsedTime = duration_cast<milliseconds>(steady_clock::now() - it->sendTimePoint); 761cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: pkg:%s is wait ACK. elapsedTime %lld", 762cc290419Sopenharmony_ci it->ToDebugString().c_str(), (long long)elapsedTime.count()); 763cc290419Sopenharmony_ci if (elapsedTime.count() >= WAIT_RESPONSE_TIME_OUT_MS) { 764cc290419Sopenharmony_ci // check the response timeout 765cc290419Sopenharmony_ci if (it->retryChance > 0) { 766cc290419Sopenharmony_ci // if it send timeout, resend it again. 767cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UartPackageManager: pkg:%s try resend it.", 768cc290419Sopenharmony_ci it->ToDebugString().c_str()); 769cc290419Sopenharmony_ci it->pkgStatus = PKG_WAIT_SEND; 770cc290419Sopenharmony_ci it->retryChance--; 771cc290419Sopenharmony_ci NotifyTransfer(); // make transfer reschedule 772cc290419Sopenharmony_ci break; // dont process anything now. 773cc290419Sopenharmony_ci } else { 774cc290419Sopenharmony_ci // the response it timeout and retry counx is 0 775cc290419Sopenharmony_ci // the link maybe not stable 776cc290419Sopenharmony_ci // let's free this session 777cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UartPackageManager: reach max retry ,free the session %u", 778cc290419Sopenharmony_ci it->sessionId); 779cc290419Sopenharmony_ci OnTransferError(GetSession(it->sessionId)); 780cc290419Sopenharmony_ci // dont reschedule here 781cc290419Sopenharmony_ci // wait next schedule from this path 782cc290419Sopenharmony_ci // OnTransferError -> FreeSession -> ClearUARTOutMap -> NotifyTransfer 783cc290419Sopenharmony_ci break; 784cc290419Sopenharmony_ci } 785cc290419Sopenharmony_ci } 786cc290419Sopenharmony_ci hasWaitPkg.emplace(it->sessionId); 787cc290419Sopenharmony_ci } 788cc290419Sopenharmony_ci it++; // next package 789cc290419Sopenharmony_ci } 790cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "UartPackageManager: send finish, have %zu pkgs", outPkgs.size()); 791cc290419Sopenharmony_ci} 792cc290419Sopenharmony_ci 793cc290419Sopenharmony_civoid HdcUARTBase::ClearUARTOutMap(uint32_t sessionId) 794cc290419Sopenharmony_ci{ 795cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s UartPackageManager clean for sessionId %u", __FUNCTION__, sessionId); 796cc290419Sopenharmony_ci size_t erased = 0; 797cc290419Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(mapOutPkgsMutex); 798cc290419Sopenharmony_ci auto it = outPkgs.begin(); 799cc290419Sopenharmony_ci while (it != outPkgs.end()) { 800cc290419Sopenharmony_ci if (it->sessionId == sessionId) { 801cc290419Sopenharmony_ci if (!it->response) { 802cc290419Sopenharmony_ci slots.Free(it->sessionId); 803cc290419Sopenharmony_ci } 804cc290419Sopenharmony_ci it = outPkgs.erase(it); 805cc290419Sopenharmony_ci erased++; 806cc290419Sopenharmony_ci } else { 807cc290419Sopenharmony_ci it++; 808cc290419Sopenharmony_ci } 809cc290419Sopenharmony_ci } 810cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s erased %zu", __FUNCTION__, erased); 811cc290419Sopenharmony_ci 812cc290419Sopenharmony_ci NotifyTransfer(); // tell transfer we maybe have some change 813cc290419Sopenharmony_ci} 814cc290419Sopenharmony_ci 815cc290419Sopenharmony_civoid HdcUARTBase::EnsureAllPkgsSent() 816cc290419Sopenharmony_ci{ 817cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s", __FUNCTION__); 818cc290419Sopenharmony_ci slots.WaitFree(); 819cc290419Sopenharmony_ci if (!outPkgs.empty()) { 820cc290419Sopenharmony_ci std::this_thread::sleep_for(1000ms); 821cc290419Sopenharmony_ci } 822cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s done.", __FUNCTION__); 823cc290419Sopenharmony_ci} 824cc290419Sopenharmony_ci 825cc290419Sopenharmony_ciRetErrCode HdcUARTBase::ValidateUartPacket(vector<uint8_t> &data, uint32_t &sessionId, 826cc290419Sopenharmony_ci uint32_t &packageIndex, size_t &packetSize) 827cc290419Sopenharmony_ci{ 828cc290419Sopenharmony_ci constexpr auto maxBufFactor = 1; 829cc290419Sopenharmony_ci struct UartHead *head = (struct UartHead *)data.data(); 830cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s %s", __FUNCTION__, head->ToDebugString().c_str()); 831cc290419Sopenharmony_ci 832cc290419Sopenharmony_ci if (memcmp(head->flag, PACKET_FLAG.c_str(), PACKET_FLAG.size()) != 0) { 833cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s,PACKET_FLAG not correct %x %x", __FUNCTION__, head->flag[0], 834cc290419Sopenharmony_ci head->flag[1]); 835cc290419Sopenharmony_ci return ERR_BUF_CHECK; 836cc290419Sopenharmony_ci } 837cc290419Sopenharmony_ci 838cc290419Sopenharmony_ci if (!head->ValidateHead()) { 839cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s head checksum not correct", __FUNCTION__); 840cc290419Sopenharmony_ci return ERR_BUF_CHECK; 841cc290419Sopenharmony_ci } 842cc290419Sopenharmony_ci // after validate , id and fullPackageLength is correct 843cc290419Sopenharmony_ci sessionId = head->sessionId; 844cc290419Sopenharmony_ci packetSize = head->dataSize + sizeof(UartHead); 845cc290419Sopenharmony_ci packageIndex = head->packageIndex; 846cc290419Sopenharmony_ci 847cc290419Sopenharmony_ci if ((head->dataSize + sizeof(UartHead)) > MAX_UART_SIZE_IOBUF * maxBufFactor) { 848cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s dataSize too larger:%d", __FUNCTION__, head->dataSize); 849cc290419Sopenharmony_ci return ERR_BUF_OVERFLOW; 850cc290419Sopenharmony_ci } 851cc290419Sopenharmony_ci 852cc290419Sopenharmony_ci if ((head->option & PKG_OPTION_RESET)) { 853cc290419Sopenharmony_ci // The Host end program is restarted, but the UART cable is still connected 854cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s host side want restart daemon, restart old sessionId:%u", 855cc290419Sopenharmony_ci __FUNCTION__, head->sessionId); 856cc290419Sopenharmony_ci ResetOldSession(head->sessionId); 857cc290419Sopenharmony_ci return ERR_IO_SOFT_RESET; 858cc290419Sopenharmony_ci } 859cc290419Sopenharmony_ci 860cc290419Sopenharmony_ci if ((head->option & PKG_OPTION_FREE)) { 861cc290419Sopenharmony_ci // other side tell us the session need reset 862cc290419Sopenharmony_ci // we should free it 863cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s other side tell us the session need free:%u", __FUNCTION__, 864cc290419Sopenharmony_ci head->sessionId); 865cc290419Sopenharmony_ci Restartession(GetSession(head->sessionId)); 866cc290419Sopenharmony_ci } 867cc290419Sopenharmony_ci 868cc290419Sopenharmony_ci // check data 869cc290419Sopenharmony_ci if (data.size() >= packetSize) { 870cc290419Sopenharmony_ci // if we have full package now ? 871cc290419Sopenharmony_ci if (!head->ValidateData()) { 872cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s data checksum not correct", __FUNCTION__); 873cc290419Sopenharmony_ci return ERR_BUF_CHECK; 874cc290419Sopenharmony_ci } 875cc290419Sopenharmony_ci if (head->IsResponsePackage()) { 876cc290419Sopenharmony_ci // response package 877cc290419Sopenharmony_ci ProcessResponsePackage(*head); 878cc290419Sopenharmony_ci } else { 879cc290419Sopenharmony_ci // link layer response for no response package 880cc290419Sopenharmony_ci ResponseUartTrans(head->sessionId, head->packageIndex, PKG_OPTION_ACK); 881cc290419Sopenharmony_ci } 882cc290419Sopenharmony_ci } 883cc290419Sopenharmony_ci 884cc290419Sopenharmony_ci return RET_SUCCESS; 885cc290419Sopenharmony_ci} 886cc290419Sopenharmony_ci 887cc290419Sopenharmony_civoid HdcUARTBase::ResponseUartTrans(uint32_t sessionId, uint32_t packageIndex, 888cc290419Sopenharmony_ci UartProtocolOption option) 889cc290419Sopenharmony_ci{ 890cc290419Sopenharmony_ci UartHead uartHeader(sessionId, option, 0, packageIndex); 891cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s option:%u", __FUNCTION__, option); 892cc290419Sopenharmony_ci RequestSendPackage(reinterpret_cast<uint8_t *>(&uartHeader), sizeof(UartHead), false); 893cc290419Sopenharmony_ci} 894cc290419Sopenharmony_ci 895cc290419Sopenharmony_ciint HdcUARTBase::SendUARTData(HSession hSession, uint8_t *data, const size_t length) 896cc290419Sopenharmony_ci{ 897cc290419Sopenharmony_ci constexpr int maxIOSize = MAX_UART_SIZE_IOBUF; 898cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "SendUARTData hSession:%u, total length:%d", hSession->sessionId, length); 899cc290419Sopenharmony_ci const int packageDataMaxSize = maxIOSize - sizeof(UartHead); 900cc290419Sopenharmony_ci size_t offset = 0; 901cc290419Sopenharmony_ci uint8_t sendDataBuf[MAX_UART_SIZE_IOBUF]; 902cc290419Sopenharmony_ci 903cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "SendUARTData data length :%d", length); 904cc290419Sopenharmony_ci 905cc290419Sopenharmony_ci do { 906cc290419Sopenharmony_ci UartHead *head = (UartHead *)sendDataBuf; 907cc290419Sopenharmony_ci if (memset_s(head, sizeof(UartHead), 0, sizeof(UartHead)) != EOK) { 908cc290419Sopenharmony_ci return ERR_BUF_RESET; 909cc290419Sopenharmony_ci } 910cc290419Sopenharmony_ci if (memcpy_s(head->flag, sizeof(head->flag), PACKET_FLAG.c_str(), PACKET_FLAG.size()) != 911cc290419Sopenharmony_ci EOK) { 912cc290419Sopenharmony_ci return ERR_BUF_COPY; 913cc290419Sopenharmony_ci } 914cc290419Sopenharmony_ci head->sessionId = hSession->sessionId; 915cc290419Sopenharmony_ci head->packageIndex = ++hSession->hUART->packageIndex; 916cc290419Sopenharmony_ci 917cc290419Sopenharmony_ci int RemainingDataSize = length - offset; 918cc290419Sopenharmony_ci if (RemainingDataSize > packageDataMaxSize) { 919cc290419Sopenharmony_ci // more than one package max data size 920cc290419Sopenharmony_ci head->dataSize = static_cast<uint16_t>(packageDataMaxSize); 921cc290419Sopenharmony_ci } else { 922cc290419Sopenharmony_ci // less then the max size 923cc290419Sopenharmony_ci head->dataSize = static_cast<uint16_t>(RemainingDataSize); 924cc290419Sopenharmony_ci // this is the last package . all the data will send after this time 925cc290419Sopenharmony_ci head->option = head->option | PKG_OPTION_TAIL; 926cc290419Sopenharmony_ci } 927cc290419Sopenharmony_ci#ifdef UART_FULL_LOG 928cc290419Sopenharmony_ci WRITE_LOG(LOG_FULL, "offset %d length %d", offset, length); 929cc290419Sopenharmony_ci#endif 930cc290419Sopenharmony_ci uint8_t *payload = sendDataBuf + sizeof(UartHead); 931cc290419Sopenharmony_ci if (EOK != 932cc290419Sopenharmony_ci memcpy_s(payload, packageDataMaxSize, (uint8_t *)data + offset, head->dataSize)) { 933cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "memcpy_s failed max %zu , need %zu", 934cc290419Sopenharmony_ci packageDataMaxSize, head->dataSize); 935cc290419Sopenharmony_ci return ERR_BUF_COPY; 936cc290419Sopenharmony_ci } 937cc290419Sopenharmony_ci offset += head->dataSize; 938cc290419Sopenharmony_ci int packageFullSize = sizeof(UartHead) + head->dataSize; 939cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "SendUARTData =============> %s", head->ToDebugString().c_str()); 940cc290419Sopenharmony_ci RequestSendPackage(sendDataBuf, packageFullSize); 941cc290419Sopenharmony_ci } while (offset != length); 942cc290419Sopenharmony_ci 943cc290419Sopenharmony_ci return offset; 944cc290419Sopenharmony_ci} 945cc290419Sopenharmony_ci 946cc290419Sopenharmony_civoid HdcUARTBase::ReadDataFromUARTStream(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) 947cc290419Sopenharmony_ci{ 948cc290419Sopenharmony_ci HSession hSession = (HSession)stream->data; 949cc290419Sopenharmony_ci HdcUARTBase *hUARTBase = (HdcUARTBase *)hSession->classModule; 950cc290419Sopenharmony_ci std::lock_guard<std::mutex> lock(hUARTBase->workThreadProcessingData); 951cc290419Sopenharmony_ci 952cc290419Sopenharmony_ci constexpr int bufSize = 1024; 953cc290419Sopenharmony_ci char buffer[bufSize] = { 0 }; 954cc290419Sopenharmony_ci if (nread < 0) { 955cc290419Sopenharmony_ci uv_err_name_r(nread, buffer, bufSize); 956cc290419Sopenharmony_ci } 957cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s sessionId:%u, nread:%zd %s streamSize %zu", __FUNCTION__, 958cc290419Sopenharmony_ci hSession->sessionId, nread, buffer, 959cc290419Sopenharmony_ci hSession->hUART->streamSize.load()); 960cc290419Sopenharmony_ci HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; 961cc290419Sopenharmony_ci if (nread <= 0 or nread > signed(hSession->hUART->streamSize)) { 962cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s nothing need to do ! because no data here", __FUNCTION__); 963cc290419Sopenharmony_ci return; 964cc290419Sopenharmony_ci } 965cc290419Sopenharmony_ci if (hSessionBase->FetchIOBuf(hSession, hSession->ioBuf, nread) < 0) { 966cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s FetchIOBuf failed , free the other side session", __FUNCTION__); 967cc290419Sopenharmony_ci // session side said the dont understand this session data 968cc290419Sopenharmony_ci // so we also need tell other side to free it session. 969cc290419Sopenharmony_ci hUARTBase->ResponseUartTrans(hSession->sessionId, ++hSession->hUART->packageIndex, 970cc290419Sopenharmony_ci PKG_OPTION_FREE); 971cc290419Sopenharmony_ci 972cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s FetchIOBuf failed , free the session", __FUNCTION__); 973cc290419Sopenharmony_ci hSessionBase->FreeSession(hSession->sessionId); 974cc290419Sopenharmony_ci } 975cc290419Sopenharmony_ci hSession->hUART->streamSize -= nread; 976cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s sessionId:%u, nread:%d", __FUNCTION__, hSession->sessionId, nread); 977cc290419Sopenharmony_ci} 978cc290419Sopenharmony_ci 979cc290419Sopenharmony_cibool HdcUARTBase::ReadyForWorkThread(HSession hSession) 980cc290419Sopenharmony_ci{ 981cc290419Sopenharmony_ci if (externInterface.UvTcpInit(&hSession->childLoop, &hSession->dataPipe[STREAM_WORK], 982cc290419Sopenharmony_ci hSession->dataFd[STREAM_WORK])) { 983cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s init child TCP failed", __FUNCTION__); 984cc290419Sopenharmony_ci return false; 985cc290419Sopenharmony_ci } 986cc290419Sopenharmony_ci hSession->dataPipe[STREAM_WORK].data = hSession; 987cc290419Sopenharmony_ci HdcSessionBase *pSession = (HdcSessionBase *)hSession->classInstance; 988cc290419Sopenharmony_ci externInterface.SetTcpOptions(&hSession->dataPipe[STREAM_WORK]); 989cc290419Sopenharmony_ci if (externInterface.UvRead((uv_stream_t *)&hSession->dataPipe[STREAM_WORK], 990cc290419Sopenharmony_ci pSession->AllocCallback, &HdcUARTBase::ReadDataFromUARTStream)) { 991cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s child TCP read failed", __FUNCTION__); 992cc290419Sopenharmony_ci return false; 993cc290419Sopenharmony_ci } 994cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s finish", __FUNCTION__); 995cc290419Sopenharmony_ci return true; 996cc290419Sopenharmony_ci} 997cc290419Sopenharmony_ci 998cc290419Sopenharmony_civoid HdcUARTBase::Restartession(const HSession session) 999cc290419Sopenharmony_ci{ 1000cc290419Sopenharmony_ci if (session != nullptr) { 1001cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s:%s", __FUNCTION__, session->ToDebugString().c_str()); 1002cc290419Sopenharmony_ci ClearUARTOutMap(session->sessionId); 1003cc290419Sopenharmony_ci sessionBase.FreeSession(session->sessionId); 1004cc290419Sopenharmony_ci } 1005cc290419Sopenharmony_ci} 1006cc290419Sopenharmony_ci 1007cc290419Sopenharmony_civoid HdcUARTBase::StopSession(HSession hSession) 1008cc290419Sopenharmony_ci{ 1009cc290419Sopenharmony_ci if (hSession != nullptr) { 1010cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s:%s", __FUNCTION__, hSession->ToDebugString().c_str()); 1011cc290419Sopenharmony_ci ClearUARTOutMap(hSession->sessionId); 1012cc290419Sopenharmony_ci } else { 1013cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "%s: clean null session", __FUNCTION__); 1014cc290419Sopenharmony_ci } 1015cc290419Sopenharmony_ci} 1016cc290419Sopenharmony_ci 1017cc290419Sopenharmony_civoid HdcUARTBase::TransferStateMachine::Wait() 1018cc290419Sopenharmony_ci{ 1019cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex); 1020cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "%s", __FUNCTION__); 1021cc290419Sopenharmony_ci if (timeout) { 1022cc290419Sopenharmony_ci auto waitTimeout = std::chrono::duration_cast<std::chrono::milliseconds>( 1023cc290419Sopenharmony_ci timeoutPoint - std::chrono::steady_clock::now()); 1024cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "wait timeout %lld", waitTimeout.count()); 1025cc290419Sopenharmony_ci if (cv.wait_for(lock, waitTimeout, [=] { return requested; }) == false) { 1026cc290419Sopenharmony_ci // must wait one timeout 1027cc290419Sopenharmony_ci // because sometime maybe not timeout but we got a request first. 1028cc290419Sopenharmony_ci timeout = false; 1029cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "timeout"); 1030cc290419Sopenharmony_ci } 1031cc290419Sopenharmony_ci } else { 1032cc290419Sopenharmony_ci cv.wait(lock, [=] { return requested; }); 1033cc290419Sopenharmony_ci } 1034cc290419Sopenharmony_ci requested = false; 1035cc290419Sopenharmony_ci} 1036cc290419Sopenharmony_ci 1037cc290419Sopenharmony_ciHdcUART::HdcUART() 1038cc290419Sopenharmony_ci{ 1039cc290419Sopenharmony_ci#ifdef _WIN32 1040cc290419Sopenharmony_ci Base::ZeroStruct(ovWrite); 1041cc290419Sopenharmony_ci ovWrite.hEvent = CreateEvent(NULL, false, false, NULL); 1042cc290419Sopenharmony_ci Base::ZeroStruct(ovRead); 1043cc290419Sopenharmony_ci ovRead.hEvent = CreateEvent(NULL, false, false, NULL); 1044cc290419Sopenharmony_ci#endif 1045cc290419Sopenharmony_ci} 1046cc290419Sopenharmony_ci 1047cc290419Sopenharmony_ciHdcUART::~HdcUART() 1048cc290419Sopenharmony_ci{ 1049cc290419Sopenharmony_ci#ifdef _WIN32 1050cc290419Sopenharmony_ci CloseHandle(ovWrite.hEvent); 1051cc290419Sopenharmony_ci ovWrite.hEvent = NULL; 1052cc290419Sopenharmony_ci CloseHandle(ovRead.hEvent); 1053cc290419Sopenharmony_ci ovRead.hEvent = NULL; 1054cc290419Sopenharmony_ci#endif 1055cc290419Sopenharmony_ci} 1056cc290419Sopenharmony_ci} // namespace Hdc 1057cc290419Sopenharmony_ci#endif // HDC_SUPPORT_UART