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