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
SendToPollFd(int fd,const uint8_t * buf,const int len)41 int ExternInterface::SendToPollFd(int fd, const uint8_t *buf, const int len)
42 {
43 return Base::SendToPollFd(fd, buf, len);
44 }
45
UvTcpInit(uv_loop_t * loop,uv_tcp_t * tcp,int socketFd)46 int 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
UvRead(uv_stream_t * stream,uv_alloc_cb allocCallBack,uv_read_cb readCallBack)55 int 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
StartWorkThread(uv_loop_t * loop,uv_work_cb pFuncWorkThread,uv_after_work_cb pFuncAfterThread,void * pThreadData)60 int 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
TryCloseHandle(const uv_handle_t * handle,uv_close_cb closeCallBack)66 void ExternInterface::TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack)
67 {
68 return Base::TryCloseHandle(handle, closeCallBack);
69 }
70
TimerUvTask(uv_loop_t * loop,void * data,uv_timer_cb cb)71 bool ExternInterface::TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb)
72 {
73 return Base::TimerUvTask(loop, data, cb);
74 }
UvTimerStart(uv_timer_t * handle,uv_timer_cb cb,uint64_t timeout,uint64_t repeat)75 bool 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
DelayDo(uv_loop_t * loop,const int delayMs,const uint8_t flag,string msg,void * data,DelayCB cb)81 bool 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
HdcUARTBase(HdcSessionBase & sessionBaseIn,ExternInterface & interfaceIn)87 HdcUARTBase::HdcUARTBase(HdcSessionBase &sessionBaseIn, ExternInterface &interfaceIn)
88 : externInterface(interfaceIn), sessionBase(sessionBaseIn)
89 {
90 uartOpened = false;
91 }
92
~HdcUARTBase(void)93 HdcUARTBase::~HdcUARTBase(void) {}
94
95 #ifndef _WIN32
GetUartSpeed(int speed)96 int 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 }
GetUartBits(int bits)121 int 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)
SetSerial(int fd,int nSpeed,int nBits,char nEvent,int nStop)136 int 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
SetSerial(int fd,int nSpeed,int nBits,char nEvent,int nStop)175 int 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
ReadUartDev(std::vector<uint8_t> & readBuf,size_t expectedSize,HdcUART & uart)230 ssize_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
WriteUartDev(uint8_t * data,const size_t length,HdcUART & uart)345 ssize_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
UartToHdcProtocol(uv_stream_t * stream,uint8_t * data,int dataSize)395 int 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
DispatchToWorkThread(HSession hSession,uint8_t * readBuf,int readBytes)441 RetErrCode 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
PackageProcess(vector<uint8_t> & data,HSession hSession)452 size_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
SendUARTRaw(HSession hSession,uint8_t * data,const size_t length)525 bool 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
UartSendToHdcStream(HSession hSession,uint8_t * data,size_t size)567 bool 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
NotifyTransfer()609 void HdcUARTBase::NotifyTransfer()
610 {
611 WRITE_LOG(LOG_DEBUG, "%s", __FUNCTION__);
612 transfer.Request();
613 }
614
615 /*
616 here we have a HandleOutputPkg vector
617 It is used to maintain the data reliability of the link layer
618 It consists of the following part
619 Log data to send (caller thread) --> RequestSendPackage
620 Send recorded data (loop sending thread) --> SendPkgInUARTOutMap
621 Process the returned reply data (loop reading thread) --> ProcessResponsePackage
622 Send reply packet (loop reading thread) --> ResponseUartTrans
623
624 The key scenarios are as follows:
625 Package is sent from side A to side B
626 Here we call the complete data package
627 package is divided into head and data
628 The response information is in the header.
629 data contains binary data.
630
631 case 1: Normal Process
632 package
633 A --> B
634 ACK
635 A <-- B
636
637 case 2: packet is incorrect
638 At least one header must be received
639 For this the B side needs to have an accept timeout.
640 There 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
644 A --> B
645 B sends NAK and A resends the packet.
646 NAK
647 A <-- B
648 package resend
649 A --> B
650
651 case 3: packet is complete lost()
652 package(complete lost)
653 A -x-> B
654 The A side needs to resend the Package after a certain timeout
655 A --> B
656 Until the B side has a data report (ACK or NAK), or the number of retransmissions reaches the upper
657 limit.
658 */
RequestSendPackage(uint8_t * data,const size_t length,bool queue)659 void 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
ProcessResponsePackage(const UartHead & head)686 void 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
SendPkgInUARTOutMap()714 void 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
ClearUARTOutMap(uint32_t sessionId)793 void 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
EnsureAllPkgsSent()815 void 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
ValidateUartPacket(vector<uint8_t> & data,uint32_t & sessionId,uint32_t & packageIndex,size_t & packetSize)825 RetErrCode 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
ResponseUartTrans(uint32_t sessionId,uint32_t packageIndex,UartProtocolOption option)887 void 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
SendUARTData(HSession hSession,uint8_t * data,const size_t length)895 int 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
ReadDataFromUARTStream(uv_stream_t * stream,ssize_t nread,const uv_buf_t * buf)946 void 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
ReadyForWorkThread(HSession hSession)979 bool 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
Restartession(const HSession session)998 void 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
StopSession(HSession hSession)1007 void 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
Wait()1017 void 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
HdcUART()1037 HdcUART::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
~HdcUART()1047 HdcUART::~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