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