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