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