1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifdef HDC_SUPPORT_UART
17
18 #include "daemon_uart.h"
19
20 #include <thread>
21 #include <fcntl.h>
22 #include <file_ex.h>
23 #include <string_ex.h>
24
25 #include <sys/file.h>
26 #include <sys/mount.h>
27 #include <sys/select.h>
28 #include <sys/time.h>
29
30 namespace Hdc {
HdcDaemonUART(HdcDaemon & daemonSessionIn,ExternInterface & externInterface)31 HdcDaemonUART::HdcDaemonUART(HdcDaemon &daemonSessionIn, ExternInterface &externInterface)
32 : HdcUARTBase(daemonSessionIn, externInterface), daemon(daemonSessionIn)
33 {
34 checkSerialPort.data = nullptr;
35 }
36
Initial(const std::string & devPathIn)37 int HdcDaemonUART::Initial(const std::string &devPathIn)
38 {
39 int ret = 0;
40 devPath = devPathIn;
41 WRITE_LOG(LOG_DEBUG, "HdcDaemonUART init");
42 if (access(devPath.c_str(), F_OK) != 0) {
43 WRITE_LOG(LOG_DEBUG, "uartMod Disable, path is %s and errno is %d.", devPath.c_str(), errno);
44 return -1;
45 }
46 #ifndef HDC_UT
47 std::string consoleActive;
48 if (OHOS::LoadStringFromFile(CONSOLE_ACTIVE_NODE, consoleActive)) {
49 consoleActive = OHOS::TrimStr(consoleActive,'\n');
50 WRITE_LOG(LOG_DEBUG, "consoleActive (%d):%s", consoleActive.length(),
51 consoleActive.c_str());
52 if (!consoleActive.empty() and devPathIn.find(consoleActive.c_str()) != std::string::npos) {
53 WRITE_LOG(LOG_FATAL,
54 "kernel use this dev(%s) as console , we can't open it as hdc uart dev",
55 devPathIn.c_str());
56 return -1;
57 }
58 }
59 #endif
60 constexpr int bufSize = 1024;
61 char buf[bufSize] = { 0 };
62 const uint16_t uartScanInterval = 1500;
63 ret = uv_timer_init(&daemon.loopMain, &checkSerialPort);
64 if (ret != 0) {
65 uv_err_name_r(ret, buf, bufSize);
66 WRITE_LOG(LOG_FATAL, "uv_timer_init failed %s", buf);
67 } else {
68 checkSerialPort.data = this;
69 ret = uv_timer_start(&checkSerialPort, UvWatchTimer, 0, uartScanInterval);
70 if (ret != 0) {
71 uv_err_name_r(ret, buf, bufSize);
72 WRITE_LOG(LOG_FATAL, "uv_timer_start failed %s", buf);
73 } else {
74 return 0;
75 }
76 }
77 return -1;
78 }
79
PrepareBufForRead()80 int HdcDaemonUART::PrepareBufForRead()
81 {
82 constexpr int bufCoefficient = 1;
83 int readMax = MAX_UART_SIZE_IOBUF * bufCoefficient;
84 dataReadBuf.clear();
85 dataReadBuf.reserve(readMax);
86 return RET_SUCCESS;
87 }
88
WatcherTimerCallBack()89 void HdcDaemonUART::WatcherTimerCallBack()
90 {
91 // try reanbel the uart device (reopen)
92 if (isAlive) {
93 return;
94 }
95 do {
96 if (uartHandle >= 0) {
97 if (CloseUartDevice() != RET_SUCCESS) {
98 break;
99 }
100 }
101 if ((OpenUartDevice() != RET_SUCCESS)) {
102 WRITE_LOG(LOG_DEBUG, "OpenUartdevice fail ! ");
103 break;
104 }
105 if ((PrepareBufForRead() != RET_SUCCESS)) {
106 WRITE_LOG(LOG_DEBUG, "PrepareBufForRead fail ! ");
107 break;
108 }
109 // read and write thread need this flag
110 isAlive = true;
111 if ((LoopUARTRead() != RET_SUCCESS)) {
112 WRITE_LOG(LOG_DEBUG, "LoopUARTRead fail ! ");
113 break;
114 }
115 if ((LoopUARTWrite() != RET_SUCCESS)) {
116 WRITE_LOG(LOG_DEBUG, "LoopUARTWrite fail ! ");
117 break;
118 }
119 return;
120 } while (false);
121 WRITE_LOG(LOG_FATAL, "WatcherTimerCallBack found some issue");
122 isAlive = false;
123 }
124
CloseUartDevice()125 int HdcDaemonUART::CloseUartDevice()
126 {
127 int ret = Base::CloseFd(uartHandle);
128 if (ret < 0) {
129 WRITE_LOG(LOG_FATAL, "CloseUartDevice failed ret: %d", ret);
130 }
131 isAlive = false;
132 return ret;
133 }
134
OpenUartDevice()135 int HdcDaemonUART::OpenUartDevice()
136 {
137 int ret = ERR_GENERIC;
138 while (true) {
139 if ((uartHandle = open(devPath.c_str(), O_RDWR | O_NOCTTY | O_NDELAY)) < 0) {
140 WRITE_LOG(LOG_WARN, "%s: cannot open uartHandle: errno=%d", devPath.c_str(), errno);
141 break;
142 }
143 uv_sleep(uartIOWaitTime100);
144 // cannot open with O_CLOEXEC, must fcntl
145 fcntl(uartHandle, F_SETFD, FD_CLOEXEC);
146 int flag = fcntl(uartHandle, F_GETFL);
147 flag &= ~O_NONBLOCK;
148 fcntl(uartHandle, F_SETFL, flag);
149 WRITE_LOG(LOG_DEBUG, "Set SetSerial ");
150 if (SetSerial(uartHandle, DEFAULT_BAUD_RATE_VALUE, UART_BIT2, 'N', 1) != RET_SUCCESS) {
151 break;
152 }
153 ret = RET_SUCCESS;
154 break;
155 }
156 if (ret != RET_SUCCESS) {
157 WRITE_LOG(LOG_DEBUG, "OpenUartdevice SerialHandle:%d fail.", uartHandle);
158 }
159 return ret;
160 }
161
ResetOldSession(uint32_t sessionId)162 void HdcDaemonUART::ResetOldSession(uint32_t sessionId)
163 {
164 if (sessionId == 0) {
165 sessionId = currentSessionId;
166 }
167 HSession hSession = daemon.AdminSession(OP_QUERY, sessionId, nullptr);
168 if (hSession == nullptr) {
169 return;
170 }
171 if (hSession->hUART != nullptr) {
172 hSession->hUART->resetIO = true;
173 }
174 // The Host side is restarted, but the USB cable is still connected
175 WRITE_LOG(LOG_WARN, "Hostside softreset to restart daemon, old sessionId:%u", sessionId);
176 OnTransferError(hSession);
177 }
178
GetSession(const uint32_t sessionId,bool create=false)179 HSession HdcDaemonUART::GetSession(const uint32_t sessionId, bool create = false)
180 {
181 HSession hSession = daemon.AdminSession(OP_QUERY, sessionId, nullptr);
182 if (hSession == nullptr and create) {
183 hSession = PrepareNewSession(sessionId);
184 }
185 return hSession;
186 }
187
OnTransferError(const HSession session)188 void HdcDaemonUART::OnTransferError(const HSession session)
189 {
190 // review maybe we can do something more ?
191 if (session != nullptr) {
192 WRITE_LOG(LOG_FATAL, "%s %s", __FUNCTION__, session->ToDebugString().c_str());
193 daemon.FreeSession(session->sessionId);
194 ClearUARTOutMap(session->sessionId);
195 }
196 }
197
OnNewHandshakeOK(const uint32_t sessionId)198 void HdcDaemonUART::OnNewHandshakeOK(const uint32_t sessionId)
199 {
200 currentSessionId = sessionId;
201 }
202
PrepareNewSession(uint32_t sessionId)203 HSession HdcDaemonUART::PrepareNewSession(uint32_t sessionId)
204 {
205 WRITE_LOG(LOG_FATAL, "%s sessionId:%u", __FUNCTION__, sessionId);
206 HSession hSession = daemon.MallocSession(false, CONN_SERIAL, this, sessionId);
207 if (!hSession) {
208 WRITE_LOG(LOG_FATAL, "new session malloc failed for sessionId:%u", sessionId);
209 return nullptr;
210 }
211 if (currentSessionId != 0) {
212 // reset old session
213 // The Host side is restarted, but the cable is still connected
214 WRITE_LOG(LOG_WARN, "New session coming, restart old sessionId:%u", currentSessionId);
215 daemon.PushAsyncMessage(currentSessionId, ASYNC_FREE_SESSION, nullptr, 0);
216 }
217 externInterface.StartWorkThread(&daemon.loopMain, daemon.SessionWorkThread,
218 Base::FinishWorkThread, hSession);
219 auto funcNewSessionUp = [](uv_timer_t *handle) -> void {
220 HSession hSession = reinterpret_cast<HSession>(handle->data);
221 HdcDaemon &daemonSession = *reinterpret_cast<HdcDaemon *>(hSession->classInstance);
222 if (hSession->childLoop.active_handles == 0) {
223 WRITE_LOG(LOG_DEBUG, "No active_handles.");
224 return;
225 }
226 if (!hSession->isDead) {
227 auto ctrl = daemonSession.BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
228 Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(),
229 ctrl.size());
230 WRITE_LOG(LOG_DEBUG, "Main thread uartio migrate finish");
231 }
232 Base::TryCloseHandle(reinterpret_cast<uv_handle_t *>(handle), Base::CloseTimerCallback);
233 };
234 externInterface.TimerUvTask(&daemon.loopMain, hSession, funcNewSessionUp);
235 return hSession;
236 }
237
238 // review Merge this with Host side
DeamonReadThread()239 void HdcDaemonUART::DeamonReadThread()
240 {
241 HdcUART deamonUart;
242 deamonUart.devUartHandle = uartHandle;
243 dataReadBuf.clear();
244 // after we got the head or something , we will expected some size
245 size_t expectedSize = 0;
246 // use < not <= because if it full , should not read again
247 while (isAlive && dataReadBuf.size() < MAX_READ_BUFFER) {
248 ssize_t bytesRead = ReadUartDev(dataReadBuf, expectedSize, deamonUart);
249 if (bytesRead == 0) {
250 WRITE_LOG(LOG_DEBUG, "%s read %zd, clean the data try read again.", __FUNCTION__,
251 bytesRead);
252 // drop current cache
253 expectedSize = 0;
254 dataReadBuf.clear();
255 continue;
256 } else if (bytesRead < 0) {
257 WRITE_LOG(LOG_DEBUG, "%s read abnormal, stop uart module.", __FUNCTION__);
258 Stop();
259 break;
260 }
261 WRITE_LOG(LOG_DEBUG, "DeamonReadThread bytesRead:%d, totalReadBytes.size():%d.", bytesRead,
262 dataReadBuf.size());
263
264 if (dataReadBuf.size() < sizeof(UartHead)) {
265 continue; // no enough ,read again
266 }
267 expectedSize = PackageProcess(dataReadBuf);
268 }
269 if (isAlive) {
270 WRITE_LOG(LOG_WARN, "totalReadSize is full %zu/%zu, DeamonReadThread exit..",
271 dataReadBuf.size(), expectedSize);
272 } else {
273 WRITE_LOG(LOG_WARN, "dev is not alive, DeamonReadThread exit..");
274 }
275 // why not free session here
276 isAlive = false;
277 return;
278 }
279
DeamonWriteThread()280 void HdcDaemonUART::DeamonWriteThread()
281 {
282 while (isAlive) {
283 WRITE_LOG(LOG_DEBUG, "DeamonWriteThread wait sendLock.");
284 transfer.Wait();
285 SendPkgInUARTOutMap();
286 }
287 WRITE_LOG(LOG_WARN, "dev is not alive, DeamonWriteThread exit..");
288 return;
289 }
290
LoopUARTRead()291 int HdcDaemonUART::LoopUARTRead()
292 {
293 try {
294 std::thread deamonReadThread(std::bind(&HdcDaemonUART::DeamonReadThread, this));
295 deamonReadThread.detach();
296 return 0;
297 } catch (...) {
298 WRITE_LOG(LOG_WARN, "create thread DeamonReadThread failed");
299 }
300 return -1;
301 }
302
LoopUARTWrite()303 int HdcDaemonUART::LoopUARTWrite()
304 {
305 try {
306 std::thread deamonWriteThread(std::bind(&HdcDaemonUART::DeamonWriteThread, this));
307 deamonWriteThread.detach();
308 return 0;
309 } catch (...) {
310 WRITE_LOG(LOG_WARN, "create thread DeamonWriteThread failed");
311 }
312 return -1;
313 }
314
IsSendReady(HSession hSession)315 bool HdcDaemonUART::IsSendReady(HSession hSession)
316 {
317 if (isAlive and !hSession->isDead and uartHandle >= 0 and !hSession->hUART->resetIO) {
318 return true;
319 } else {
320 if (!isAlive) {
321 WRITE_LOG(LOG_WARN, "!isAlive");
322 } else if (hSession->isDead) {
323 WRITE_LOG(LOG_WARN, "session isDead");
324 } else if (uartHandle < 0) {
325 WRITE_LOG(LOG_WARN, "uartHandle is not valid");
326 } else if (hSession->hUART->resetIO) {
327 WRITE_LOG(LOG_WARN, "session have resetIO");
328 }
329 return false;
330 }
331 };
332
~HdcDaemonUART()333 HdcDaemonUART::~HdcDaemonUART()
334 {
335 Stop();
336 }
337
Stop()338 void HdcDaemonUART::Stop()
339 {
340 WRITE_LOG(LOG_DEBUG, "%s run!", __FUNCTION__);
341 if (!stopped) {
342 stopped = true;
343 std::lock_guard<std::mutex> lock(workThreadProcessingData);
344
345 // maybe some data response not back to host
346 // like smode need response.
347 ResponseUartTrans(currentSessionId, 0, PKG_OPTION_FREE);
348 EnsureAllPkgsSent();
349 isAlive = false;
350 WRITE_LOG(LOG_DEBUG, "%s free main session", __FUNCTION__);
351 if (checkSerialPort.data != nullptr) {
352 externInterface.TryCloseHandle((uv_handle_t *)&checkSerialPort);
353 checkSerialPort.data = nullptr;
354 }
355 CloseUartDevice();
356 WRITE_LOG(LOG_DEBUG, "%s free main session finish", __FUNCTION__);
357 }
358 }
359 } // namespace Hdc
360 #endif // HDC_SUPPORT_UART
361