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