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 "host_uart.h"
19cc290419Sopenharmony_ci
20cc290419Sopenharmony_ci#include <mutex>
21cc290419Sopenharmony_ci#include <thread>
22cc290419Sopenharmony_ci
23cc290419Sopenharmony_ci#include "server.h"
24cc290419Sopenharmony_ci
25cc290419Sopenharmony_ciusing namespace std::chrono_literals;
26cc290419Sopenharmony_cinamespace Hdc {
27cc290419Sopenharmony_ciHdcHostUART::HdcHostUART(HdcServer &serverIn, ExternInterface &externInterface)
28cc290419Sopenharmony_ci    : HdcUARTBase(serverIn, externInterface), server(serverIn)
29cc290419Sopenharmony_ci{
30cc290419Sopenharmony_ci    uv_timer_init(&server.loopMain, &devUartWatcher);
31cc290419Sopenharmony_ci}
32cc290419Sopenharmony_ci
33cc290419Sopenharmony_ciHdcHostUART::~HdcHostUART()
34cc290419Sopenharmony_ci{
35cc290419Sopenharmony_ci    Stop();
36cc290419Sopenharmony_ci}
37cc290419Sopenharmony_ci
38cc290419Sopenharmony_ciint HdcHostUART::Initial()
39cc290419Sopenharmony_ci{
40cc290419Sopenharmony_ci    uartOpened = false; // modRunning
41cc290419Sopenharmony_ci    return StartupUARTWork();
42cc290419Sopenharmony_ci}
43cc290419Sopenharmony_ci
44cc290419Sopenharmony_cibool HdcHostUART::NeedStop(const HSession hSession)
45cc290419Sopenharmony_ci{
46cc290419Sopenharmony_ci    return (!uartOpened or (hSession->isDead and hSession->ref == 0));
47cc290419Sopenharmony_ci}
48cc290419Sopenharmony_ci
49cc290419Sopenharmony_cibool HdcHostUART::IsDeviceOpened(const HdcUART &uart)
50cc290419Sopenharmony_ci{
51cc290419Sopenharmony_ci    // review why not use uartOpened?
52cc290419Sopenharmony_ci#ifdef HOST_MINGW
53cc290419Sopenharmony_ci    return uart.devUartHandle != INVALID_HANDLE_VALUE;
54cc290419Sopenharmony_ci#else
55cc290419Sopenharmony_ci    return uart.devUartHandle >= 0;
56cc290419Sopenharmony_ci#endif
57cc290419Sopenharmony_ci}
58cc290419Sopenharmony_ci
59cc290419Sopenharmony_civoid HdcHostUART::UartWriteThread()
60cc290419Sopenharmony_ci{
61cc290419Sopenharmony_ci    // this thread don't care session.
62cc290419Sopenharmony_ci    while (true) {
63cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s wait sendLock.", __FUNCTION__);
64cc290419Sopenharmony_ci        transfer.Wait();
65cc290419Sopenharmony_ci        // it almost in wait , so we check stop after wait.
66cc290419Sopenharmony_ci        if (stopped) {
67cc290419Sopenharmony_ci            break;
68cc290419Sopenharmony_ci        }
69cc290419Sopenharmony_ci        SendPkgInUARTOutMap();
70cc290419Sopenharmony_ci    }
71cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "Leave %s", __FUNCTION__);
72cc290419Sopenharmony_ci    return;
73cc290419Sopenharmony_ci}
74cc290419Sopenharmony_ci
75cc290419Sopenharmony_civoid HdcHostUART::UartReadThread(HSession hSession)
76cc290419Sopenharmony_ci{
77cc290419Sopenharmony_ci    HUART hUART = hSession->hUART;
78cc290419Sopenharmony_ci    vector<uint8_t> dataReadBuf; // each thread/session have it own data buff
79cc290419Sopenharmony_ci    // If something unexpected happens , max buffer size we allow
80cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s devUartHandle:%d", __FUNCTION__, hUART->devUartHandle);
81cc290419Sopenharmony_ci    size_t expectedSize = 0;
82cc290419Sopenharmony_ci    while (dataReadBuf.size() < MAX_READ_BUFFER) {
83cc290419Sopenharmony_ci        if (NeedStop(hSession)) {
84cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "%s stop ", __FUNCTION__);
85cc290419Sopenharmony_ci            break;
86cc290419Sopenharmony_ci        }
87cc290419Sopenharmony_ci        ssize_t bytesRead = ReadUartDev(dataReadBuf, expectedSize, *hUART);
88cc290419Sopenharmony_ci        if (bytesRead < 0) {
89cc290419Sopenharmony_ci            WRITE_LOG(LOG_INFO, "%s read got fail , free the session", __FUNCTION__);
90cc290419Sopenharmony_ci            OnTransferError(hSession);
91cc290419Sopenharmony_ci        } else if (bytesRead == 0) {
92cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s read %zd, clean the data try read again.", __FUNCTION__,
93cc290419Sopenharmony_ci                      bytesRead);
94cc290419Sopenharmony_ci            // drop current cache
95cc290419Sopenharmony_ci            expectedSize = 0;
96cc290419Sopenharmony_ci            dataReadBuf.clear();
97cc290419Sopenharmony_ci            continue;
98cc290419Sopenharmony_ci        }
99cc290419Sopenharmony_ci
100cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s bytesRead:%d, dataReadBuf.size():%d.", __FUNCTION__, bytesRead,
101cc290419Sopenharmony_ci                  dataReadBuf.size());
102cc290419Sopenharmony_ci
103cc290419Sopenharmony_ci        if (dataReadBuf.size() < sizeof(UartHead)) {
104cc290419Sopenharmony_ci            continue; // no enough ,read again
105cc290419Sopenharmony_ci        }
106cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s PackageProcess dataReadBuf.size():%d.", __FUNCTION__,
107cc290419Sopenharmony_ci                  dataReadBuf.size());
108cc290419Sopenharmony_ci        expectedSize = PackageProcess(dataReadBuf, hSession);
109cc290419Sopenharmony_ci    }
110cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "Leave %s", __FUNCTION__);
111cc290419Sopenharmony_ci    return;
112cc290419Sopenharmony_ci}
113cc290419Sopenharmony_ci
114cc290419Sopenharmony_ci// review why not use QueryDosDevice ?
115cc290419Sopenharmony_cibool HdcHostUART::EnumSerialPort(bool &portChange)
116cc290419Sopenharmony_ci{
117cc290419Sopenharmony_ci    std::vector<string> newPortInfo;
118cc290419Sopenharmony_ci    serialPortRemoved.clear();
119cc290419Sopenharmony_ci    bool bRet = true;
120cc290419Sopenharmony_ci
121cc290419Sopenharmony_ci#ifdef HOST_MINGW
122cc290419Sopenharmony_ci    constexpr int MAX_KEY_LENGTH = 255;
123cc290419Sopenharmony_ci    constexpr int MAX_VALUE_NAME = 16383;
124cc290419Sopenharmony_ci    HKEY hKey;
125cc290419Sopenharmony_ci    TCHAR achValue[MAX_VALUE_NAME];    // buffer for subkey name
126cc290419Sopenharmony_ci    DWORD cchValue = MAX_VALUE_NAME;   // size of name string
127cc290419Sopenharmony_ci    TCHAR achClass[MAX_PATH] = _T(""); // buffer for class name
128cc290419Sopenharmony_ci    DWORD cchClassName = MAX_PATH;     // size of class string
129cc290419Sopenharmony_ci    DWORD cSubKeys = 0;                // number of subkeys
130cc290419Sopenharmony_ci    DWORD cbMaxSubKey;                 // longest subkey size
131cc290419Sopenharmony_ci    DWORD cchMaxClass;                 // longest class string
132cc290419Sopenharmony_ci    DWORD cKeyNum;                     // number of values for key
133cc290419Sopenharmony_ci    DWORD cchMaxValue;                 // longest value name
134cc290419Sopenharmony_ci    DWORD cbMaxValueData;              // longest value data
135cc290419Sopenharmony_ci    DWORD cbSecurityDescriptor;        // size of security descriptor
136cc290419Sopenharmony_ci    FILETIME ftLastWriteTime;          // last write time
137cc290419Sopenharmony_ci    LSTATUS iRet = -1;
138cc290419Sopenharmony_ci    std::string port;
139cc290419Sopenharmony_ci    TCHAR strDSName[MAX_VALUE_NAME];
140cc290419Sopenharmony_ci    if (memset_s(strDSName, sizeof(TCHAR) * MAX_VALUE_NAME, 0, sizeof(TCHAR) * MAX_VALUE_NAME) !=
141cc290419Sopenharmony_ci        EOK) {
142cc290419Sopenharmony_ci        return false;
143cc290419Sopenharmony_ci    }
144cc290419Sopenharmony_ci    DWORD nValueType = 0;
145cc290419Sopenharmony_ci    DWORD nBuffLen = 10;
146cc290419Sopenharmony_ci    if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0,
147cc290419Sopenharmony_ci                                      KEY_READ, &hKey)) {
148cc290419Sopenharmony_ci        // Get the class name and the value count.
149cc290419Sopenharmony_ci        iRet = RegQueryInfoKey(hKey, achClass, &cchClassName, NULL, &cSubKeys, &cbMaxSubKey,
150cc290419Sopenharmony_ci                               &cchMaxClass, &cKeyNum, &cchMaxValue, &cbMaxValueData,
151cc290419Sopenharmony_ci                               &cbSecurityDescriptor, &ftLastWriteTime);
152cc290419Sopenharmony_ci        // Enumerate the key values.
153cc290419Sopenharmony_ci        if (ERROR_SUCCESS == iRet) {
154cc290419Sopenharmony_ci            for (DWORD i = 0; i < cKeyNum; i++) {
155cc290419Sopenharmony_ci                cchValue = MAX_VALUE_NAME;
156cc290419Sopenharmony_ci                achValue[0] = '\0';
157cc290419Sopenharmony_ci                nBuffLen = MAX_KEY_LENGTH;
158cc290419Sopenharmony_ci                if (ERROR_SUCCESS == RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL,
159cc290419Sopenharmony_ci                                                  (LPBYTE)strDSName, &nBuffLen)) {
160cc290419Sopenharmony_ci#ifdef UNICODE
161cc290419Sopenharmony_ci                    strPortName = WstringToString(strDSName);
162cc290419Sopenharmony_ci#else
163cc290419Sopenharmony_ci                    port = std::string(strDSName);
164cc290419Sopenharmony_ci#endif
165cc290419Sopenharmony_ci                    newPortInfo.push_back(port);
166cc290419Sopenharmony_ci                    auto it = std::find(serialPortInfo.begin(), serialPortInfo.end(), port);
167cc290419Sopenharmony_ci                    if (it == serialPortInfo.end()) {
168cc290419Sopenharmony_ci                        portChange = true;
169cc290419Sopenharmony_ci                        WRITE_LOG(LOG_DEBUG, "%s:new port %s", __FUNCTION__, port.c_str());
170cc290419Sopenharmony_ci                    }
171cc290419Sopenharmony_ci                } else {
172cc290419Sopenharmony_ci                    bRet = false;
173cc290419Sopenharmony_ci                    WRITE_LOG(LOG_DEBUG, "%s RegEnumValue fail. %d", __FUNCTION__, GetLastError());
174cc290419Sopenharmony_ci                }
175cc290419Sopenharmony_ci            }
176cc290419Sopenharmony_ci        } else {
177cc290419Sopenharmony_ci            bRet = false;
178cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s RegQueryInfoKey failed %d", __FUNCTION__, GetLastError());
179cc290419Sopenharmony_ci        }
180cc290419Sopenharmony_ci    } else {
181cc290419Sopenharmony_ci        bRet = false;
182cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s RegOpenKeyEx fail %d", __FUNCTION__, GetLastError());
183cc290419Sopenharmony_ci    }
184cc290419Sopenharmony_ci    RegCloseKey(hKey);
185cc290419Sopenharmony_ci#endif
186cc290419Sopenharmony_ci#if defined(HOST_LINUX)||defined(HOST_MAC)
187cc290419Sopenharmony_ci    DIR *dir = opendir("/dev");
188cc290419Sopenharmony_ci    dirent *p = NULL;
189cc290419Sopenharmony_ci
190cc290419Sopenharmony_ci    while (dir != nullptr && ((p = readdir(dir)) != nullptr)) {
191cc290419Sopenharmony_ci#ifdef HOST_LINUX
192cc290419Sopenharmony_ci        if (p->d_name[0] != '.' && string(p->d_name).find("tty") != std::string::npos) {
193cc290419Sopenharmony_ci#else
194cc290419Sopenharmony_ci        if (p->d_name[0] != '.' && string(p->d_name).find("serial") != std::string::npos) {
195cc290419Sopenharmony_ci#endif
196cc290419Sopenharmony_ci            string port = "/dev/" + string(p->d_name);
197cc290419Sopenharmony_ci            if (port.find("/dev/ttyUSB") == 0 || port.find("/dev/ttySerial") == 0 || port.find("/dev/cu.") == 0) {
198cc290419Sopenharmony_ci                newPortInfo.push_back(port);
199cc290419Sopenharmony_ci                auto it = std::find(serialPortInfo.begin(), serialPortInfo.end(), port);
200cc290419Sopenharmony_ci                if (it == serialPortInfo.end()) {
201cc290419Sopenharmony_ci                    portChange = true;
202cc290419Sopenharmony_ci                    WRITE_LOG(LOG_DEBUG, "new port:%s", port.c_str());
203cc290419Sopenharmony_ci                }
204cc290419Sopenharmony_ci            }
205cc290419Sopenharmony_ci        }
206cc290419Sopenharmony_ci    }
207cc290419Sopenharmony_ci    if (dir != nullptr) {
208cc290419Sopenharmony_ci        closedir(dir);
209cc290419Sopenharmony_ci    }
210cc290419Sopenharmony_ci#endif
211cc290419Sopenharmony_ci    for (auto &oldPort : serialPortInfo) {
212cc290419Sopenharmony_ci        auto it = std::find(newPortInfo.begin(), newPortInfo.end(), oldPort);
213cc290419Sopenharmony_ci        if (it == newPortInfo.end()) {
214cc290419Sopenharmony_ci            // not found in new port list
215cc290419Sopenharmony_ci            // we need remove the connect info
216cc290419Sopenharmony_ci            serialPortRemoved.emplace_back(oldPort);
217cc290419Sopenharmony_ci        }
218cc290419Sopenharmony_ci    }
219cc290419Sopenharmony_ci
220cc290419Sopenharmony_ci    if (!portChange) {
221cc290419Sopenharmony_ci        // new scan empty , same as port changed
222cc290419Sopenharmony_ci        if (serialPortInfo.size() != newPortInfo.size()) {
223cc290419Sopenharmony_ci            portChange = true;
224cc290419Sopenharmony_ci        }
225cc290419Sopenharmony_ci    }
226cc290419Sopenharmony_ci    if (portChange) {
227cc290419Sopenharmony_ci        serialPortInfo.swap(newPortInfo);
228cc290419Sopenharmony_ci    }
229cc290419Sopenharmony_ci    return bRet;
230cc290419Sopenharmony_ci}
231cc290419Sopenharmony_ci
232cc290419Sopenharmony_ci#ifdef HOST_MINGW
233cc290419Sopenharmony_cistd::string WstringToString(const std::wstring &wstr)
234cc290419Sopenharmony_ci{
235cc290419Sopenharmony_ci    if (wstr.empty()) {
236cc290419Sopenharmony_ci        return std::string();
237cc290419Sopenharmony_ci    }
238cc290419Sopenharmony_ci    int size = WideCharToMultiByte(CP_ACP, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
239cc290419Sopenharmony_ci    std::string ret = std::string(size, 0);
240cc290419Sopenharmony_ci    WideCharToMultiByte(CP_ACP, 0, &wstr[0], (int)wstr.size(), &ret[0], size, NULL,
241cc290419Sopenharmony_ci                        NULL); // CP_UTF8
242cc290419Sopenharmony_ci    return ret;
243cc290419Sopenharmony_ci}
244cc290419Sopenharmony_ci
245cc290419Sopenharmony_ci// review rename for same func from linux
246cc290419Sopenharmony_ciint HdcHostUART::WinSetSerial(HUART hUART, string serialPort, int byteSize, int eqBaudRate)
247cc290419Sopenharmony_ci{
248cc290419Sopenharmony_ci    int winRet = RET_SUCCESS;
249cc290419Sopenharmony_ci    COMMTIMEOUTS timeouts;
250cc290419Sopenharmony_ci    GetCommTimeouts(hUART->devUartHandle, &timeouts);
251cc290419Sopenharmony_ci    int interTimeout = 5;
252cc290419Sopenharmony_ci    timeouts.ReadIntervalTimeout = interTimeout;
253cc290419Sopenharmony_ci    timeouts.ReadTotalTimeoutMultiplier = 0;
254cc290419Sopenharmony_ci    timeouts.ReadTotalTimeoutConstant = 0;
255cc290419Sopenharmony_ci    timeouts.WriteTotalTimeoutMultiplier = 0;
256cc290419Sopenharmony_ci    timeouts.WriteTotalTimeoutConstant = 0;
257cc290419Sopenharmony_ci    SetCommTimeouts(hUART->devUartHandle, &timeouts);
258cc290419Sopenharmony_ci    constexpr int max = DEFAULT_BAUD_RATE_VALUE / 8 * 2; // 2 second buffer size
259cc290419Sopenharmony_ci    do {
260cc290419Sopenharmony_ci        if (!SetupComm(hUART->devUartHandle, max, max)) {
261cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "SetupComm %s fail, err:%d.", serialPort.c_str(), GetLastError());
262cc290419Sopenharmony_ci            winRet = ERR_GENERIC;
263cc290419Sopenharmony_ci            break;
264cc290419Sopenharmony_ci        }
265cc290419Sopenharmony_ci        DCB dcb;
266cc290419Sopenharmony_ci        if (!GetCommState(hUART->devUartHandle, &dcb)) {
267cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "GetCommState %s fail, err:%d.", serialPort.c_str(),
268cc290419Sopenharmony_ci                      GetLastError());
269cc290419Sopenharmony_ci            winRet = ERR_GENERIC;
270cc290419Sopenharmony_ci        }
271cc290419Sopenharmony_ci        dcb.DCBlength = sizeof(DCB);
272cc290419Sopenharmony_ci        dcb.BaudRate = eqBaudRate;
273cc290419Sopenharmony_ci        dcb.Parity = 0;
274cc290419Sopenharmony_ci        dcb.ByteSize = byteSize;
275cc290419Sopenharmony_ci        dcb.StopBits = ONESTOPBIT;
276cc290419Sopenharmony_ci        if (!SetCommState(hUART->devUartHandle, &dcb)) {
277cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "SetCommState %s fail, err:%d.", serialPort.c_str(),
278cc290419Sopenharmony_ci                      GetLastError());
279cc290419Sopenharmony_ci            winRet = ERR_GENERIC;
280cc290419Sopenharmony_ci            break;
281cc290419Sopenharmony_ci        }
282cc290419Sopenharmony_ci        if (!PurgeComm(hUART->devUartHandle,
283cc290419Sopenharmony_ci                       PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT)) {
284cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "PurgeComm  %s fail, err:%d.", serialPort.c_str(), GetLastError());
285cc290419Sopenharmony_ci            winRet = ERR_GENERIC;
286cc290419Sopenharmony_ci            break;
287cc290419Sopenharmony_ci        }
288cc290419Sopenharmony_ci        DWORD dwError;
289cc290419Sopenharmony_ci        COMSTAT cs;
290cc290419Sopenharmony_ci        if (!ClearCommError(hUART->devUartHandle, &dwError, &cs)) {
291cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "ClearCommError %s fail, err:%d.", serialPort.c_str(),
292cc290419Sopenharmony_ci                      GetLastError());
293cc290419Sopenharmony_ci            winRet = ERR_GENERIC;
294cc290419Sopenharmony_ci            break;
295cc290419Sopenharmony_ci        }
296cc290419Sopenharmony_ci    } while (false);
297cc290419Sopenharmony_ci    if (winRet != RET_SUCCESS) {
298cc290419Sopenharmony_ci        CloseSerialPort(hUART);
299cc290419Sopenharmony_ci    }
300cc290419Sopenharmony_ci    return winRet;
301cc290419Sopenharmony_ci}
302cc290419Sopenharmony_ci#endif // HOST_MINGW
303cc290419Sopenharmony_ci
304cc290419Sopenharmony_cibool HdcHostUART::WaitUartIdle(HdcUART &uart, bool retry)
305cc290419Sopenharmony_ci{
306cc290419Sopenharmony_ci    std::vector<uint8_t> readBuf;
307cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s clear read", __FUNCTION__);
308cc290419Sopenharmony_ci    ssize_t ret = ReadUartDev(readBuf, 1, uart);
309cc290419Sopenharmony_ci    if (ret == 0) {
310cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s port read timeout", __FUNCTION__);
311cc290419Sopenharmony_ci        return true;
312cc290419Sopenharmony_ci    } else {
313cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "%s port read something %zd", __FUNCTION__, ret);
314cc290419Sopenharmony_ci        if (retry) {
315cc290419Sopenharmony_ci            // we will read again , but only retry one time
316cc290419Sopenharmony_ci            return WaitUartIdle(uart, false);
317cc290419Sopenharmony_ci        } else {
318cc290419Sopenharmony_ci            return false;
319cc290419Sopenharmony_ci        }
320cc290419Sopenharmony_ci    }
321cc290419Sopenharmony_ci    return false;
322cc290419Sopenharmony_ci}
323cc290419Sopenharmony_ci
324cc290419Sopenharmony_ciint HdcHostUART::OpenSerialPort(const std::string &connectKey)
325cc290419Sopenharmony_ci{
326cc290419Sopenharmony_ci    HdcUART uart;
327cc290419Sopenharmony_ci    std::string portName;
328cc290419Sopenharmony_ci    uint32_t baudRate;
329cc290419Sopenharmony_ci    static int ret = 0;
330cc290419Sopenharmony_ci
331cc290419Sopenharmony_ci    if (memset_s(&uart, sizeof(HdcUART), 0, sizeof(HdcUART)) != EOK) {
332cc290419Sopenharmony_ci        return -1;
333cc290419Sopenharmony_ci    }
334cc290419Sopenharmony_ci
335cc290419Sopenharmony_ci    if (!GetPortFromKey(connectKey, portName, baudRate)) {
336cc290419Sopenharmony_ci        WRITE_LOG(LOG_ALL, "%s unknown format %s", __FUNCTION__, Hdc::MaskString(connectKey).c_str());
337cc290419Sopenharmony_ci        return -1;
338cc290419Sopenharmony_ci    }
339cc290419Sopenharmony_ci    do {
340cc290419Sopenharmony_ci        ret = 0;
341cc290419Sopenharmony_ci        WRITE_LOG(LOG_ALL, "%s try to open %s with rate %u", __FUNCTION__, portName.c_str(),
342cc290419Sopenharmony_ci                  baudRate);
343cc290419Sopenharmony_ci
344cc290419Sopenharmony_ci#ifdef HOST_MINGW
345cc290419Sopenharmony_ci        constexpr int numTmp = 2;
346cc290419Sopenharmony_ci        // review change to wstring ?
347cc290419Sopenharmony_ci        TCHAR apiBuf[PORT_NAME_LEN * numTmp];
348cc290419Sopenharmony_ci#ifdef UNICODE
349cc290419Sopenharmony_ci        int cnt = _stprintf_s(apiBuf, sizeof(apiBuf), _T("\\\\.\\%S"), port.c_str());
350cc290419Sopenharmony_ci#else
351cc290419Sopenharmony_ci        int cnt = _stprintf_s(apiBuf, sizeof(apiBuf), _T("\\\\.\\%s"), portName.c_str());
352cc290419Sopenharmony_ci#endif
353cc290419Sopenharmony_ci        if (cnt < 0) {
354cc290419Sopenharmony_ci            ret = ERR_GENERIC;
355cc290419Sopenharmony_ci            break;
356cc290419Sopenharmony_ci        }
357cc290419Sopenharmony_ci        DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
358cc290419Sopenharmony_ci        uart.devUartHandle = CreateFile(apiBuf, GENERIC_READ | GENERIC_WRITE, 0, NULL,
359cc290419Sopenharmony_ci                                        OPEN_EXISTING, dwFlagsAndAttributes, NULL);
360cc290419Sopenharmony_ci        if (uart.devUartHandle == INVALID_HANDLE_VALUE) {
361cc290419Sopenharmony_ci            ret = ERR_GENERIC;
362cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s CreateFile %s err:%d.", __FUNCTION__, portName.c_str(),
363cc290419Sopenharmony_ci                      GetLastError());
364cc290419Sopenharmony_ci            break; // review for onethan one uart , here we need change to continue?
365cc290419Sopenharmony_ci        } else {
366cc290419Sopenharmony_ci            uart.serialPort = portName;
367cc290419Sopenharmony_ci        }
368cc290419Sopenharmony_ci        ret = WinSetSerial(&uart, uart.serialPort, UART_BIT2, baudRate);
369cc290419Sopenharmony_ci        if (ret != RET_SUCCESS) {
370cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "%s WinSetSerial:%s fail.", __FUNCTION__, uart.serialPort.c_str());
371cc290419Sopenharmony_ci            break;
372cc290419Sopenharmony_ci        }
373cc290419Sopenharmony_ci#endif
374cc290419Sopenharmony_ci
375cc290419Sopenharmony_ci#if defined(HOST_LINUX)||defined(HOST_MAC)
376cc290419Sopenharmony_ci        string uartName = Base::CanonicalizeSpecPath(portName);
377cc290419Sopenharmony_ci        uart.devUartHandle = open(uartName.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
378cc290419Sopenharmony_ci        if (uart.devUartHandle < 0) {
379cc290419Sopenharmony_ci            constexpr int bufSize = 1024;
380cc290419Sopenharmony_ci            char buf[bufSize] = { 0 };
381cc290419Sopenharmony_ci            strerror_r(errno, buf, bufSize);
382cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "Linux open serial port failed, serialPort:%s, Message : %s",
383cc290419Sopenharmony_ci                      uart.serialPort.c_str(), buf);
384cc290419Sopenharmony_ci            ret = ERR_GENERIC;
385cc290419Sopenharmony_ci            break;
386cc290419Sopenharmony_ci        }
387cc290419Sopenharmony_ci        {
388cc290419Sopenharmony_ci            uart.serialPort = portName;
389cc290419Sopenharmony_ci        }
390cc290419Sopenharmony_ci        SetSerial(uart.devUartHandle, baudRate, UART_BIT2, 'N', 1);
391cc290419Sopenharmony_ci#endif
392cc290419Sopenharmony_ci        // if the dev is idle
393cc290419Sopenharmony_ci        if (!WaitUartIdle(uart)) {
394cc290419Sopenharmony_ci            ret = ERR_GENERIC;
395cc290419Sopenharmony_ci            WRITE_LOG(LOG_INFO, "This is not a Idle UART port: %s", uart.serialPort.c_str());
396cc290419Sopenharmony_ci            break;
397cc290419Sopenharmony_ci        }
398cc290419Sopenharmony_ci        if (!ConnectMyNeed(&uart, connectKey)) {
399cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "ConnectMyNeed failed");
400cc290419Sopenharmony_ci            ret = ERR_GENERIC;
401cc290419Sopenharmony_ci            break;
402cc290419Sopenharmony_ci        } else {
403cc290419Sopenharmony_ci            uartOpened = true;
404cc290419Sopenharmony_ci            WRITE_LOG(LOG_INFO,
405cc290419Sopenharmony_ci                      "Serial Open Successfully! uart.serialPort:%s "
406cc290419Sopenharmony_ci                      "devUartHandle:%d",
407cc290419Sopenharmony_ci                      uart.serialPort.c_str(), uart.devUartHandle);
408cc290419Sopenharmony_ci        }
409cc290419Sopenharmony_ci        break;
410cc290419Sopenharmony_ci    } while (false);
411cc290419Sopenharmony_ci    if (ret != RET_SUCCESS) {
412cc290419Sopenharmony_ci        CloseSerialPort(&uart);
413cc290419Sopenharmony_ci    }
414cc290419Sopenharmony_ci    return ret;
415cc290419Sopenharmony_ci}
416cc290419Sopenharmony_ci
417cc290419Sopenharmony_civoid HdcHostUART::UpdateUARTDaemonInfo(const std::string &connectKey, HSession hSession,
418cc290419Sopenharmony_ci                                       ConnStatus connStatus)
419cc290419Sopenharmony_ci{
420cc290419Sopenharmony_ci    // add to list
421cc290419Sopenharmony_ci    HdcDaemonInformation diNew;
422cc290419Sopenharmony_ci    HDaemonInfo diNewPtr = &diNew;
423cc290419Sopenharmony_ci    diNew.connectKey = connectKey;
424cc290419Sopenharmony_ci    diNew.connType = CONN_SERIAL;
425cc290419Sopenharmony_ci    diNew.connStatus = connStatus;
426cc290419Sopenharmony_ci    diNew.hSession = hSession;
427cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s uart connectKey :%s session %s change to %d", __FUNCTION__,
428cc290419Sopenharmony_ci              connectKey.c_str(),
429cc290419Sopenharmony_ci              hSession == nullptr ? "<null>" : hSession->ToDebugString().c_str(), connStatus);
430cc290419Sopenharmony_ci    if (connStatus == STATUS_UNKNOW) {
431cc290419Sopenharmony_ci        server.AdminDaemonMap(OP_REMOVE, connectKey, diNewPtr);
432cc290419Sopenharmony_ci        if (hSession != nullptr and hSession->hUART != nullptr) {
433cc290419Sopenharmony_ci            connectedPorts.erase(hSession->hUART->serialPort);
434cc290419Sopenharmony_ci        }
435cc290419Sopenharmony_ci    } else {
436cc290419Sopenharmony_ci        if (connStatus == STATUS_CONNECTED) {
437cc290419Sopenharmony_ci            if (hSession != nullptr and hSession->hUART != nullptr) {
438cc290419Sopenharmony_ci                connectedPorts.emplace(hSession->hUART->serialPort);
439cc290419Sopenharmony_ci            }
440cc290419Sopenharmony_ci        }
441cc290419Sopenharmony_ci        HDaemonInfo diOldPtr = nullptr;
442cc290419Sopenharmony_ci        server.AdminDaemonMap(OP_QUERY, connectKey, diOldPtr);
443cc290419Sopenharmony_ci        if (diOldPtr == nullptr) {
444cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s add new di", __FUNCTION__);
445cc290419Sopenharmony_ci            server.AdminDaemonMap(OP_ADD, connectKey, diNewPtr);
446cc290419Sopenharmony_ci        } else {
447cc290419Sopenharmony_ci            server.AdminDaemonMap(OP_UPDATE, connectKey, diNewPtr);
448cc290419Sopenharmony_ci        }
449cc290419Sopenharmony_ci    }
450cc290419Sopenharmony_ci}
451cc290419Sopenharmony_ci
452cc290419Sopenharmony_cibool HdcHostUART::StartUartReadThread(HSession hSession)
453cc290419Sopenharmony_ci{
454cc290419Sopenharmony_ci    try {
455cc290419Sopenharmony_ci        HUART hUART = hSession->hUART;
456cc290419Sopenharmony_ci        hUART->readThread = std::thread([this, hSession]() { this->UartReadThread(hSession); });
457cc290419Sopenharmony_ci    } catch (...) {
458cc290419Sopenharmony_ci        server.FreeSession(hSession->sessionId);
459cc290419Sopenharmony_ci        UpdateUARTDaemonInfo(hSession->connectKey, hSession, STATUS_UNKNOW);
460cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "%s failed err", __FUNCTION__);
461cc290419Sopenharmony_ci        return false;
462cc290419Sopenharmony_ci    }
463cc290419Sopenharmony_ci
464cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "%s success.", __FUNCTION__);
465cc290419Sopenharmony_ci    return true;
466cc290419Sopenharmony_ci}
467cc290419Sopenharmony_ci
468cc290419Sopenharmony_cibool HdcHostUART::StartUartSendThread()
469cc290419Sopenharmony_ci{
470cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s.", __FUNCTION__);
471cc290419Sopenharmony_ci    try {
472cc290419Sopenharmony_ci        sendThread = std::thread([this]() { this->UartWriteThread(); });
473cc290419Sopenharmony_ci    } catch (...) {
474cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "%s sendThread create failed", __FUNCTION__);
475cc290419Sopenharmony_ci        return false;
476cc290419Sopenharmony_ci    }
477cc290419Sopenharmony_ci
478cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "%s success.", __FUNCTION__);
479cc290419Sopenharmony_ci    return true;
480cc290419Sopenharmony_ci}
481cc290419Sopenharmony_ci
482cc290419Sopenharmony_ci// Determines that daemonInfo must have the device
483cc290419Sopenharmony_ciHSession HdcHostUART::ConnectDaemonByUart(const HSession hSession, const HDaemonInfo)
484cc290419Sopenharmony_ci{
485cc290419Sopenharmony_ci    if (!uartOpened) {
486cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s non uart opened.", __FUNCTION__);
487cc290419Sopenharmony_ci        return nullptr;
488cc290419Sopenharmony_ci    }
489cc290419Sopenharmony_ci    HUART hUART = hSession->hUART;
490cc290419Sopenharmony_ci    UpdateUARTDaemonInfo(hSession->connectKey, hSession, STATUS_READY);
491cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s :%s", __FUNCTION__, hUART->serialPort.c_str());
492cc290419Sopenharmony_ci    if (!StartUartReadThread(hSession)) {
493cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s StartUartReadThread fail.", __FUNCTION__);
494cc290419Sopenharmony_ci        return nullptr;
495cc290419Sopenharmony_ci    }
496cc290419Sopenharmony_ci
497cc290419Sopenharmony_ci    externInterface.StartWorkThread(&server.loopMain, server.SessionWorkThread,
498cc290419Sopenharmony_ci                                    Base::FinishWorkThread, hSession);
499cc290419Sopenharmony_ci    // wait for thread up
500cc290419Sopenharmony_ci    while (hSession->childLoop.active_handles == 0) {
501cc290419Sopenharmony_ci        uv_sleep(1);
502cc290419Sopenharmony_ci    }
503cc290419Sopenharmony_ci    auto ctrl = server.BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
504cc290419Sopenharmony_ci    externInterface.SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
505cc290419Sopenharmony_ci    return hSession;
506cc290419Sopenharmony_ci}
507cc290419Sopenharmony_ci
508cc290419Sopenharmony_ciRetErrCode HdcHostUART::StartupUARTWork()
509cc290419Sopenharmony_ci{
510cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s", __FUNCTION__);
511cc290419Sopenharmony_ci    devUartWatcher.data = this;
512cc290419Sopenharmony_ci    constexpr int interval = 3000;
513cc290419Sopenharmony_ci    constexpr int delay = 1000;
514cc290419Sopenharmony_ci    if (externInterface.UvTimerStart(&devUartWatcher, UvWatchUartDevPlugin, delay, interval) != 0) {
515cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "devUartWatcher start fail");
516cc290419Sopenharmony_ci        return ERR_GENERIC;
517cc290419Sopenharmony_ci    }
518cc290419Sopenharmony_ci    if (!StartUartSendThread()) {
519cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s StartUartSendThread fail.", __FUNCTION__);
520cc290419Sopenharmony_ci        return ERR_GENERIC;
521cc290419Sopenharmony_ci    }
522cc290419Sopenharmony_ci    return RET_SUCCESS;
523cc290419Sopenharmony_ci}
524cc290419Sopenharmony_ci
525cc290419Sopenharmony_ciHSession HdcHostUART::ConnectDaemon(const std::string &connectKey)
526cc290419Sopenharmony_ci{
527cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s", __FUNCTION__);
528cc290419Sopenharmony_ci    OpenSerialPort(connectKey);
529cc290419Sopenharmony_ci    return nullptr;
530cc290419Sopenharmony_ci}
531cc290419Sopenharmony_ci
532cc290419Sopenharmony_ci/*
533cc290419Sopenharmony_ciThis function does the following:
534cc290419Sopenharmony_ci1. Existing serial device, check whether a session is established, if not, go to establish
535cc290419Sopenharmony_ci2. The connection is established but the serial device does not exist, delete the session
536cc290419Sopenharmony_ci*/
537cc290419Sopenharmony_civoid HdcHostUART::WatchUartDevPlugin()
538cc290419Sopenharmony_ci{
539cc290419Sopenharmony_ci    std::lock_guard<std::mutex> lock(semUartDevCheck);
540cc290419Sopenharmony_ci    bool portChange = false;
541cc290419Sopenharmony_ci
542cc290419Sopenharmony_ci    if (!EnumSerialPort(portChange)) {
543cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "%s enumDetailsSerialPorts fail.", __FUNCTION__);
544cc290419Sopenharmony_ci    } else if (portChange) {
545cc290419Sopenharmony_ci        for (const auto &port : serialPortInfo) {
546cc290419Sopenharmony_ci            WRITE_LOG(LOG_INFO, "%s found uart port :%s", __FUNCTION__, port.c_str());
547cc290419Sopenharmony_ci            // check port have session
548cc290419Sopenharmony_ci            HDaemonInfo hdi = nullptr;
549cc290419Sopenharmony_ci            server.AdminDaemonMap(OP_QUERY, port, hdi);
550cc290419Sopenharmony_ci            if (hdi == nullptr and connectedPorts.find(port) == connectedPorts.end()) {
551cc290419Sopenharmony_ci                UpdateUARTDaemonInfo(port, nullptr, STATUS_READY);
552cc290419Sopenharmony_ci            }
553cc290419Sopenharmony_ci        }
554cc290419Sopenharmony_ci        for (const auto &port : serialPortRemoved) {
555cc290419Sopenharmony_ci            WRITE_LOG(LOG_INFO, "%s remove uart port :%s", __FUNCTION__, port.c_str());
556cc290419Sopenharmony_ci            // check port have session
557cc290419Sopenharmony_ci            HDaemonInfo hdi = nullptr;
558cc290419Sopenharmony_ci            server.AdminDaemonMap(OP_QUERY, port, hdi);
559cc290419Sopenharmony_ci            if (hdi != nullptr and hdi->hSession == nullptr) {
560cc290419Sopenharmony_ci                // we only remove the empty port
561cc290419Sopenharmony_ci                UpdateUARTDaemonInfo(port, nullptr, STATUS_UNKNOW);
562cc290419Sopenharmony_ci            }
563cc290419Sopenharmony_ci        }
564cc290419Sopenharmony_ci    }
565cc290419Sopenharmony_ci}
566cc290419Sopenharmony_ci
567cc290419Sopenharmony_cibool HdcHostUART::ConnectMyNeed(HUART hUART, std::string connectKey)
568cc290419Sopenharmony_ci{
569cc290419Sopenharmony_ci    // we never use port to connect, we use connect key
570cc290419Sopenharmony_ci    if (connectKey.empty()) {
571cc290419Sopenharmony_ci        connectKey = hUART->serialPort;
572cc290419Sopenharmony_ci    }
573cc290419Sopenharmony_ci    if (connectKey != hUART->serialPort) {
574cc290419Sopenharmony_ci        UpdateUARTDaemonInfo(hUART->serialPort, nullptr, STATUS_UNKNOW);
575cc290419Sopenharmony_ci    }
576cc290419Sopenharmony_ci    UpdateUARTDaemonInfo(connectKey, nullptr, STATUS_READY);
577cc290419Sopenharmony_ci
578cc290419Sopenharmony_ci    HSession hSession = server.MallocSession(true, CONN_SERIAL, this);
579cc290419Sopenharmony_ci    if (!hSession) {
580cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "malloc serial session failed for %s", Hdc::MaskString(connectKey).c_str());
581cc290419Sopenharmony_ci        return false;
582cc290419Sopenharmony_ci    }
583cc290419Sopenharmony_ci    hSession->connectKey = connectKey;
584cc290419Sopenharmony_ci#if defined(HOST_LINUX)||defined(HOST_MAC)
585cc290419Sopenharmony_ci    hSession->hUART->devUartHandle = hUART->devUartHandle;
586cc290419Sopenharmony_ci#elif defined(HOST_MINGW)
587cc290419Sopenharmony_ci    hSession->hUART->devUartHandle = hUART->devUartHandle;
588cc290419Sopenharmony_ci#endif
589cc290419Sopenharmony_ci
590cc290419Sopenharmony_ci    hSession->isCheck = isCheck;
591cc290419Sopenharmony_ci    hSession->hUART->serialPort = hUART->serialPort;
592cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s connectkey:%s,port:%s", __FUNCTION__, Hdc::MaskString(hSession->connectKey).c_str(),
593cc290419Sopenharmony_ci              hUART->serialPort.c_str());
594cc290419Sopenharmony_ci    uv_timer_t *waitTimeDoCmd = new(std::nothrow) uv_timer_t;
595cc290419Sopenharmony_ci    if (waitTimeDoCmd == nullptr) {
596cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "ConnectMyNeed new waitTimeDoCmd failed");
597cc290419Sopenharmony_ci        server.FreeSession(hSession->sessionId);
598cc290419Sopenharmony_ci        return false;
599cc290419Sopenharmony_ci    }
600cc290419Sopenharmony_ci    uv_timer_init(&server.loopMain, waitTimeDoCmd);
601cc290419Sopenharmony_ci    waitTimeDoCmd->data = hSession;
602cc290419Sopenharmony_ci    if (externInterface.UvTimerStart(waitTimeDoCmd, server.UartPreConnect, UV_TIMEOUT, UV_REPEAT) !=
603cc290419Sopenharmony_ci        RET_SUCCESS) {
604cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "%s for %s:%s fail.", __FUNCTION__, Hdc::MaskString(hSession->connectKey).c_str(),
605cc290419Sopenharmony_ci                  hUART->serialPort.c_str());
606cc290419Sopenharmony_ci        server.FreeSession(hSession->sessionId);
607cc290419Sopenharmony_ci        return false;
608cc290419Sopenharmony_ci    }
609cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s %s register a session", __FUNCTION__, hUART->serialPort.c_str());
610cc290419Sopenharmony_ci
611cc290419Sopenharmony_ci    return true;
612cc290419Sopenharmony_ci}
613cc290419Sopenharmony_ci
614cc290419Sopenharmony_civoid HdcHostUART::KickoutZombie(HSession hSession)
615cc290419Sopenharmony_ci{
616cc290419Sopenharmony_ci    if (hSession == nullptr or hSession->hUART == nullptr or hSession->isDead) {
617cc290419Sopenharmony_ci        return;
618cc290419Sopenharmony_ci    }
619cc290419Sopenharmony_ci#ifdef _WIN32
620cc290419Sopenharmony_ci    if (hSession->hUART->devUartHandle == INVALID_HANDLE_VALUE) {
621cc290419Sopenharmony_ci        return;
622cc290419Sopenharmony_ci    }
623cc290419Sopenharmony_ci#else
624cc290419Sopenharmony_ci    if (hSession->hUART->devUartHandle < 0) {
625cc290419Sopenharmony_ci        return;
626cc290419Sopenharmony_ci    }
627cc290419Sopenharmony_ci#endif
628cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s FreeSession %s", __FUNCTION__, hSession->ToDebugString().c_str());
629cc290419Sopenharmony_ci    server.FreeSession(hSession->sessionId);
630cc290419Sopenharmony_ci}
631cc290419Sopenharmony_ci
632cc290419Sopenharmony_ciHSession HdcHostUART::GetSession(const uint32_t sessionId, bool)
633cc290419Sopenharmony_ci{
634cc290419Sopenharmony_ci    return server.AdminSession(OP_QUERY, sessionId, nullptr);
635cc290419Sopenharmony_ci}
636cc290419Sopenharmony_civoid HdcHostUART::CloseSerialPort(const HUART hUART)
637cc290419Sopenharmony_ci{
638cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s try to close dev handle %d", __FUNCTION__, hUART->devUartHandle);
639cc290419Sopenharmony_ci
640cc290419Sopenharmony_ci#ifdef _WIN32
641cc290419Sopenharmony_ci    if (hUART->devUartHandle != INVALID_HANDLE_VALUE) {
642cc290419Sopenharmony_ci        CloseHandle(hUART->devUartHandle);
643cc290419Sopenharmony_ci        hUART->devUartHandle = INVALID_HANDLE_VALUE;
644cc290419Sopenharmony_ci    }
645cc290419Sopenharmony_ci#else
646cc290419Sopenharmony_ci    if (hUART->devUartHandle != -1) {
647cc290419Sopenharmony_ci        Base::CloseFd(hUART->devUartHandle);
648cc290419Sopenharmony_ci        hUART->devUartHandle = -1;
649cc290419Sopenharmony_ci    }
650cc290419Sopenharmony_ci#endif
651cc290419Sopenharmony_ci}
652cc290419Sopenharmony_ci
653cc290419Sopenharmony_civoid HdcHostUART::OnTransferError(const HSession session)
654cc290419Sopenharmony_ci{
655cc290419Sopenharmony_ci    if (session != nullptr) {
656cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "%s:%s", __FUNCTION__, session->ToDebugString().c_str());
657cc290419Sopenharmony_ci        if (session->hUART != nullptr) {
658cc290419Sopenharmony_ci            if (IsDeviceOpened(*session->hUART)) {
659cc290419Sopenharmony_ci                // same device dont echo twice to client
660cc290419Sopenharmony_ci                string echoStr = "ERR: uart link layer transmission error.\n";
661cc290419Sopenharmony_ci                server.EchoToClientsForSession(session->sessionId, echoStr);
662cc290419Sopenharmony_ci            }
663cc290419Sopenharmony_ci            // 1. dev opened by other application
664cc290419Sopenharmony_ci            // 2. dev is plug out
665cc290419Sopenharmony_ci            // 3. dev line is broken ?
666cc290419Sopenharmony_ci            // we set the status to empty
667cc290419Sopenharmony_ci            // watcher will reopen it if it can find this again
668cc290419Sopenharmony_ci            CloseSerialPort(session->hUART);
669cc290419Sopenharmony_ci            UpdateUARTDaemonInfo(session->connectKey, session, STATUS_OFFLINE);
670cc290419Sopenharmony_ci        }
671cc290419Sopenharmony_ci
672cc290419Sopenharmony_ci        server.FreeSession(session->sessionId);
673cc290419Sopenharmony_ci        ClearUARTOutMap(session->sessionId);
674cc290419Sopenharmony_ci    }
675cc290419Sopenharmony_ci}
676cc290419Sopenharmony_ci
677cc290419Sopenharmony_ci// review what about merge Restartession with OnTransferError ?
678cc290419Sopenharmony_civoid HdcHostUART::Restartession(const HSession session)
679cc290419Sopenharmony_ci{
680cc290419Sopenharmony_ci    HdcUARTBase::Restartession(session);
681cc290419Sopenharmony_ci    // allow timer watcher make a new session.
682cc290419Sopenharmony_ci    if (session != nullptr and session->hUART != nullptr) {
683cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "%s reset serialPort:%s", __FUNCTION__,
684cc290419Sopenharmony_ci                  session->hUART->serialPort.c_str());
685cc290419Sopenharmony_ci        CloseSerialPort(session->hUART); // huart will free , so we must clost it here
686cc290419Sopenharmony_ci        server.EchoToClientsForSession(session->sessionId,
687cc290419Sopenharmony_ci                                       "uart link released by daemon. need connect again.");
688cc290419Sopenharmony_ci    }
689cc290419Sopenharmony_ci}
690cc290419Sopenharmony_ci
691cc290419Sopenharmony_civoid HdcHostUART::StopSession(HSession hSession)
692cc290419Sopenharmony_ci{
693cc290419Sopenharmony_ci    if (hSession == nullptr) {
694cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "%s hSession is null", __FUNCTION__);
695cc290419Sopenharmony_ci        return;
696cc290419Sopenharmony_ci    }
697cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s hSession %s will be stop and free", __FUNCTION__,
698cc290419Sopenharmony_ci              hSession->ToDebugString().c_str());
699cc290419Sopenharmony_ci    HUART hUART = hSession->hUART;
700cc290419Sopenharmony_ci    if (hUART == nullptr) {
701cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "%s hUART is null", __FUNCTION__);
702cc290419Sopenharmony_ci    } else {
703cc290419Sopenharmony_ci#ifdef _WIN32
704cc290419Sopenharmony_ci        CancelIoEx(hUART->devUartHandle, NULL);
705cc290419Sopenharmony_ci#endif
706cc290419Sopenharmony_ci        // we make select always have a timeout in linux
707cc290419Sopenharmony_ci        // also we make a mark here
708cc290419Sopenharmony_ci        // ReadUartDev will return for this flag
709cc290419Sopenharmony_ci        hUART->ioCancel = true;
710cc290419Sopenharmony_ci
711cc290419Sopenharmony_ci        if (hUART->readThread.joinable()) {
712cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "wait readThread Stop");
713cc290419Sopenharmony_ci            hUART->readThread.join();
714cc290419Sopenharmony_ci        } else {
715cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "readThread is not joinable");
716cc290419Sopenharmony_ci        }
717cc290419Sopenharmony_ci    }
718cc290419Sopenharmony_ci
719cc290419Sopenharmony_ci    // call the base side
720cc290419Sopenharmony_ci    HdcUARTBase::StopSession(hSession);
721cc290419Sopenharmony_ci}
722cc290419Sopenharmony_ci
723cc290419Sopenharmony_cistd::vector<std::string> HdcHostUART::StringSplit(std::string source, std::string split)
724cc290419Sopenharmony_ci{
725cc290419Sopenharmony_ci    std::vector<std::string> result;
726cc290419Sopenharmony_ci
727cc290419Sopenharmony_ci    // find
728cc290419Sopenharmony_ci    if (!split.empty()) {
729cc290419Sopenharmony_ci        size_t pos = 0;
730cc290419Sopenharmony_ci        while ((pos = source.find(split)) != std::string::npos) {
731cc290419Sopenharmony_ci            // split
732cc290419Sopenharmony_ci            std::string token = source.substr(0, pos);
733cc290419Sopenharmony_ci            if (!token.empty()) {
734cc290419Sopenharmony_ci                result.push_back(token);
735cc290419Sopenharmony_ci            }
736cc290419Sopenharmony_ci            source.erase(0, pos + split.length());
737cc290419Sopenharmony_ci        }
738cc290419Sopenharmony_ci    }
739cc290419Sopenharmony_ci    // add last token
740cc290419Sopenharmony_ci    if (!source.empty()) {
741cc290419Sopenharmony_ci        result.push_back(source);
742cc290419Sopenharmony_ci    }
743cc290419Sopenharmony_ci    return result;
744cc290419Sopenharmony_ci}
745cc290419Sopenharmony_ci
746cc290419Sopenharmony_cibool HdcHostUART::GetPortFromKey(const std::string &connectKey, std::string &portName,
747cc290419Sopenharmony_ci                                 uint32_t &baudRate)
748cc290419Sopenharmony_ci{
749cc290419Sopenharmony_ci    // we support UART_NAME:UART_RATE format
750cc290419Sopenharmony_ci    // like COM5:115200
751cc290419Sopenharmony_ci    constexpr size_t TWO_ARGS = 2;
752cc290419Sopenharmony_ci    std::vector<std::string> result = StringSplit(connectKey, ",");
753cc290419Sopenharmony_ci    if (result.size() == TWO_ARGS) {
754cc290419Sopenharmony_ci        portName = result[0];
755cc290419Sopenharmony_ci        try {
756cc290419Sopenharmony_ci            baudRate = static_cast<uint32_t>(std::stoul(result[1]));
757cc290419Sopenharmony_ci        } catch (...) {
758cc290419Sopenharmony_ci            return false;
759cc290419Sopenharmony_ci        }
760cc290419Sopenharmony_ci        return true;
761cc290419Sopenharmony_ci    } else if (result.size() == 1) {
762cc290419Sopenharmony_ci        portName = result[0];
763cc290419Sopenharmony_ci        baudRate = DEFAULT_BAUD_RATE_VALUE;
764cc290419Sopenharmony_ci        return true;
765cc290419Sopenharmony_ci    } else {
766cc290419Sopenharmony_ci        return false;
767cc290419Sopenharmony_ci    }
768cc290419Sopenharmony_ci}
769cc290419Sopenharmony_ci
770cc290419Sopenharmony_civoid HdcHostUART::SendUartSoftReset(HSession hSession, uint32_t sessionId)
771cc290419Sopenharmony_ci{
772cc290419Sopenharmony_ci    UartHead resetPackage(sessionId, PKG_OPTION_RESET);
773cc290419Sopenharmony_ci    resetPackage.dataSize = sizeof(UartHead);
774cc290419Sopenharmony_ci    RequestSendPackage(reinterpret_cast<uint8_t *>(&resetPackage), sizeof(UartHead), false);
775cc290419Sopenharmony_ci}
776cc290419Sopenharmony_ci
777cc290419Sopenharmony_civoid HdcHostUART::Stop()
778cc290419Sopenharmony_ci{
779cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "%s Stop!", __FUNCTION__);
780cc290419Sopenharmony_ci    if (!stopped) {
781cc290419Sopenharmony_ci        externInterface.TryCloseHandle((uv_handle_t *)&devUartWatcher);
782cc290419Sopenharmony_ci        uartOpened = false;
783cc290419Sopenharmony_ci        stopped = true;
784cc290419Sopenharmony_ci        // just click it for exit
785cc290419Sopenharmony_ci        NotifyTransfer();
786cc290419Sopenharmony_ci        if (sendThread.joinable()) {
787cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s wait sendThread Stop!", __FUNCTION__);
788cc290419Sopenharmony_ci            sendThread.join();
789cc290419Sopenharmony_ci        } else {
790cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "%s sendThread is not joinable", __FUNCTION__);
791cc290419Sopenharmony_ci        }
792cc290419Sopenharmony_ci    }
793cc290419Sopenharmony_ci}
794cc290419Sopenharmony_ci} // namespace Hdc
795cc290419Sopenharmony_ci#endif // HDC_SUPPORT_UART
796