• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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