• 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 
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