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#include "daemon_usb.h" 16cc290419Sopenharmony_ci#include <cerrno> 17cc290419Sopenharmony_ci#include <cstddef> 18cc290419Sopenharmony_ci#include "arpa/inet.h" 19cc290419Sopenharmony_ci#include "asm-generic/int-ll64.h" 20cc290419Sopenharmony_ci#include "fcntl.h" 21cc290419Sopenharmony_ci#include "linux/usb/functionfs.h" 22cc290419Sopenharmony_ci#include "new" 23cc290419Sopenharmony_ci#include "sched.h" 24cc290419Sopenharmony_ci#include "system_depend.h" 25cc290419Sopenharmony_ci#include "unistd.h" 26cc290419Sopenharmony_ci#include "uv/unix.h" 27cc290419Sopenharmony_ci#include "daemon.h" 28cc290419Sopenharmony_ci#include "usb_ffs.h" 29cc290419Sopenharmony_ci 30cc290419Sopenharmony_cinamespace Hdc { 31cc290419Sopenharmony_cistatic constexpr int CONFIG_COUNT2 = 2; 32cc290419Sopenharmony_cistatic constexpr int CONFIG_COUNT3 = 3; 33cc290419Sopenharmony_cistatic constexpr int CONFIG_COUNT5 = 5; 34cc290419Sopenharmony_ci 35cc290419Sopenharmony_cistruct UvData { 36cc290419Sopenharmony_ci HdcDaemonUSB *daemonUsb; 37cc290419Sopenharmony_ci const uint8_t *buf; 38cc290419Sopenharmony_ci}; 39cc290419Sopenharmony_ci 40cc290419Sopenharmony_ciHdcDaemonUSB::HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase) 41cc290419Sopenharmony_ci : HdcUSBBase(serverOrDaemonIn, ptrMainBase) 42cc290419Sopenharmony_ci{ 43cc290419Sopenharmony_ci} 44cc290419Sopenharmony_ci 45cc290419Sopenharmony_ciHdcDaemonUSB::~HdcDaemonUSB() 46cc290419Sopenharmony_ci{ 47cc290419Sopenharmony_ci // Closed in the IO loop, no longer closing CLOSE ENDPOINT 48cc290419Sopenharmony_ci Base::CloseFd(controlEp); 49cc290419Sopenharmony_ci if (ctxRecv.buf) { 50cc290419Sopenharmony_ci delete[] ctxRecv.buf; 51cc290419Sopenharmony_ci } 52cc290419Sopenharmony_ci uv_fs_req_cleanup(&ctxRecv.req); 53cc290419Sopenharmony_ci} 54cc290419Sopenharmony_ci 55cc290419Sopenharmony_civoid HdcDaemonUSB::Stop() 56cc290419Sopenharmony_ci{ 57cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop"); 58cc290419Sopenharmony_ci // Here only clean up the IO-related resources, session related resources clear reason to clean up the session 59cc290419Sopenharmony_ci // module 60cc290419Sopenharmony_ci modRunning = false; 61cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session"); 62cc290419Sopenharmony_ci Base::TryCloseHandle((uv_handle_t *)&checkEP); 63cc290419Sopenharmony_ci CloseEndpoint(&usbHandle); 64cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session finish"); 65cc290419Sopenharmony_ci} 66cc290419Sopenharmony_ci 67cc290419Sopenharmony_cistring HdcDaemonUSB::GetDevPath(const std::string &path) 68cc290419Sopenharmony_ci{ 69cc290419Sopenharmony_ci DIR *dir = ::opendir(path.c_str()); 70cc290419Sopenharmony_ci if (dir == nullptr) { 71cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s: cannot open devpath: errno: %d", path.c_str(), errno); 72cc290419Sopenharmony_ci return ""; 73cc290419Sopenharmony_ci } 74cc290419Sopenharmony_ci 75cc290419Sopenharmony_ci string res = USB_FFS_BASE; 76cc290419Sopenharmony_ci string node; 77cc290419Sopenharmony_ci int count = 0; 78cc290419Sopenharmony_ci struct dirent *entry = nullptr; 79cc290419Sopenharmony_ci while ((entry = ::readdir(dir))) { 80cc290419Sopenharmony_ci if (*entry->d_name == '.') { 81cc290419Sopenharmony_ci continue; 82cc290419Sopenharmony_ci } 83cc290419Sopenharmony_ci node = entry->d_name; 84cc290419Sopenharmony_ci ++count; 85cc290419Sopenharmony_ci } 86cc290419Sopenharmony_ci if (count > 1) { 87cc290419Sopenharmony_ci res += "hdc"; 88cc290419Sopenharmony_ci } else { 89cc290419Sopenharmony_ci res += node; 90cc290419Sopenharmony_ci } 91cc290419Sopenharmony_ci ::closedir(dir); 92cc290419Sopenharmony_ci return res; 93cc290419Sopenharmony_ci} 94cc290419Sopenharmony_ci 95cc290419Sopenharmony_ciint HdcDaemonUSB::GetMaxPacketSize(int fdFfs) 96cc290419Sopenharmony_ci{ 97cc290419Sopenharmony_ci // no ioctl support, todo dynamic get 98cc290419Sopenharmony_ci return MAX_PACKET_SIZE_HISPEED; 99cc290419Sopenharmony_ci} 100cc290419Sopenharmony_ci 101cc290419Sopenharmony_ciint HdcDaemonUSB::Initial() 102cc290419Sopenharmony_ci{ 103cc290419Sopenharmony_ci // after Linux-3.8,kernel switch to the USB Function FS 104cc290419Sopenharmony_ci // Implement USB hdc function in user space 105cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB init"); 106cc290419Sopenharmony_ci basePath = GetDevPath(USB_FFS_BASE); 107cc290419Sopenharmony_ci if (access((basePath + "/ep0").c_str(), F_OK) != 0) { 108cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG,"Only support usb-ffs, make sure kernel3.8+ and usb-ffs enabled, " 109cc290419Sopenharmony_ci "usbmode disabled: errno: %d, basePath: %s ", errno, basePath.c_str()); 110cc290419Sopenharmony_ci return ERR_API_FAIL; 111cc290419Sopenharmony_ci } 112cc290419Sopenharmony_ci ctxRecv.thisClass = this; 113cc290419Sopenharmony_ci ctxRecv.bufSizeMax = Base::GetUsbffsBulkSize(); 114cc290419Sopenharmony_ci ctxRecv.buf = new uint8_t[ctxRecv.bufSizeMax](); 115cc290419Sopenharmony_ci if (!ctxRecv.buf) { 116cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Init alloc memory failed"); 117cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 118cc290419Sopenharmony_ci } 119cc290419Sopenharmony_ci 120cc290419Sopenharmony_ci HdcDaemon *daemon = (HdcDaemon *)clsMainBase; 121cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB::Initiall"); 122cc290419Sopenharmony_ci uv_timer_init(&daemon->loopMain, &checkEP); 123cc290419Sopenharmony_ci checkEP.data = this; 124cc290419Sopenharmony_ci uv_timer_start(&checkEP, WatchEPTimer, 0, TIME_BASE); 125cc290419Sopenharmony_ci return 0; 126cc290419Sopenharmony_ci} 127cc290419Sopenharmony_ci 128cc290419Sopenharmony_ci// make gnuc++ happy. Clang support direct assignment value to structure, buf g++ weakness 129cc290419Sopenharmony_civoid HdcDaemonUSB::FillUsbV2Head(UsbFunctionfsDescV2 &descUsbFfs) 130cc290419Sopenharmony_ci{ 131cc290419Sopenharmony_ci descUsbFfs.head.magic = LONG_LE(FUNCTIONFS_DESCRIPTORS_MAGIC_V2); 132cc290419Sopenharmony_ci descUsbFfs.head.length = LONG_LE(sizeof(descUsbFfs)); 133cc290419Sopenharmony_ci descUsbFfs.head.flags 134cc290419Sopenharmony_ci = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC; 135cc290419Sopenharmony_ci descUsbFfs.config1Count = CONFIG_COUNT3; 136cc290419Sopenharmony_ci descUsbFfs.config2Count = CONFIG_COUNT3; 137cc290419Sopenharmony_ci descUsbFfs.config3Count = CONFIG_COUNT5; 138cc290419Sopenharmony_ci descUsbFfs.configWosCount = CONFIG_COUNT2; 139cc290419Sopenharmony_ci descUsbFfs.config1Desc = config1; 140cc290419Sopenharmony_ci descUsbFfs.config2Desc = config2; 141cc290419Sopenharmony_ci descUsbFfs.config3Desc = config3; 142cc290419Sopenharmony_ci descUsbFfs.wosHead = g_wosHead; 143cc290419Sopenharmony_ci descUsbFfs.wosDesc = g_wosDesc; 144cc290419Sopenharmony_ci descUsbFfs.osPropHead = g_osPropHead; 145cc290419Sopenharmony_ci descUsbFfs.osPropValues = g_osPropValues; 146cc290419Sopenharmony_ci} 147cc290419Sopenharmony_ci 148cc290419Sopenharmony_ci// DAEMON end USB module USB-FFS EP port connection 149cc290419Sopenharmony_ciint HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) 150cc290419Sopenharmony_ci{ 151cc290419Sopenharmony_ci int ret = ERR_GENERIC; 152cc290419Sopenharmony_ci struct UsbFunctionfsDescV2 descUsbFfs = {}; 153cc290419Sopenharmony_ci FillUsbV2Head(descUsbFfs); 154cc290419Sopenharmony_ci while (true) { 155cc290419Sopenharmony_ci if (controlEp <= 0) { 156cc290419Sopenharmony_ci // After the control port sends the instruction, the device is initialized by the device to the HOST host, 157cc290419Sopenharmony_ci // which can be found for USB devices. Do not send initialization to the EP0 control port, the USB 158cc290419Sopenharmony_ci // device will not be initialized by Host 159cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Begin send to control(EP0) for usb descriptor init"); 160cc290419Sopenharmony_ci string ep0Path = basePath + "/ep0"; 161cc290419Sopenharmony_ci if ((controlEp = open(ep0Path.c_str(), O_RDWR)) < 0) { 162cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s: cannot open control endpoint: errno=%d", ep0Path.c_str(), errno); 163cc290419Sopenharmony_ci break; 164cc290419Sopenharmony_ci } 165cc290419Sopenharmony_ci if (write(controlEp, &descUsbFfs, sizeof(descUsbFfs)) < 0) { 166cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s: write ffs configs failed: errno=%d", ep0Path.c_str(), errno); 167cc290419Sopenharmony_ci break; 168cc290419Sopenharmony_ci } 169cc290419Sopenharmony_ci if (write(controlEp, &USB_FFS_VALUE, sizeof(USB_FFS_VALUE)) < 0) { 170cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s: write USB_FFS_VALUE failed: errno=%d", ep0Path.c_str(), errno); 171cc290419Sopenharmony_ci break; 172cc290419Sopenharmony_ci } 173cc290419Sopenharmony_ci // active usbrc,Send USB initialization signal 174cc290419Sopenharmony_ci SystemDepend::SetDevItem("sys.usb.ffs.ready.hdc", "0"); 175cc290419Sopenharmony_ci SystemDepend::SetDevItem("sys.usb.ffs.ready", "1"); 176cc290419Sopenharmony_ci SystemDepend::SetDevItem("sys.usb.ffs.ready.hdc", "1"); 177cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "ConnectEPPoint ctrl init finish, set usb-ffs ready"); 178cc290419Sopenharmony_ci } 179cc290419Sopenharmony_ci string outPath = basePath + "/ep1"; 180cc290419Sopenharmony_ci if ((hUSB->bulkOut = open(outPath.c_str(), O_RDWR)) < 0) { 181cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s: cannot open bulk-out ep: errno=%d", outPath.c_str(), errno); 182cc290419Sopenharmony_ci break; 183cc290419Sopenharmony_ci } 184cc290419Sopenharmony_ci string inPath = basePath + "/ep2"; 185cc290419Sopenharmony_ci if ((hUSB->bulkIn = open(inPath.c_str(), O_RDWR)) < 0) { 186cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "%s: cannot open bulk-in ep: errno=%d", inPath.c_str(), errno); 187cc290419Sopenharmony_ci break; 188cc290419Sopenharmony_ci } 189cc290419Sopenharmony_ci // cannot open with O_CLOEXEC, must fcntl 190cc290419Sopenharmony_ci fcntl(controlEp, F_SETFD, FD_CLOEXEC); 191cc290419Sopenharmony_ci fcntl(hUSB->bulkOut, F_SETFD, FD_CLOEXEC); 192cc290419Sopenharmony_ci fcntl(hUSB->bulkIn, F_SETFD, FD_CLOEXEC); 193cc290419Sopenharmony_ci hUSB->wMaxPacketSizeSend = GetMaxPacketSize(hUSB->bulkIn); 194cc290419Sopenharmony_ci 195cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "New bulk in\\out open bulkout:%d bulkin:%d", hUSB->bulkOut, hUSB->bulkIn); 196cc290419Sopenharmony_ci ret = RET_SUCCESS; 197cc290419Sopenharmony_ci break; 198cc290419Sopenharmony_ci } 199cc290419Sopenharmony_ci if (ret != RET_SUCCESS) { 200cc290419Sopenharmony_ci CloseEndpoint(hUSB, true); 201cc290419Sopenharmony_ci } 202cc290419Sopenharmony_ci return ret; 203cc290419Sopenharmony_ci} 204cc290419Sopenharmony_ci 205cc290419Sopenharmony_civoid HdcDaemonUSB::CloseEndpoint(HUSB hUSB, bool closeCtrlEp) 206cc290419Sopenharmony_ci{ 207cc290419Sopenharmony_ci Base::CloseFd(hUSB->bulkIn); 208cc290419Sopenharmony_ci Base::CloseFd(hUSB->bulkOut); 209cc290419Sopenharmony_ci if (controlEp > 0 && closeCtrlEp) { 210cc290419Sopenharmony_ci Base::CloseFd(controlEp); 211cc290419Sopenharmony_ci controlEp = 0; 212cc290419Sopenharmony_ci } 213cc290419Sopenharmony_ci isAlive = false; 214cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "DaemonUSB close endpoint"); 215cc290419Sopenharmony_ci} 216cc290419Sopenharmony_ci 217cc290419Sopenharmony_civoid HdcDaemonUSB::ResetOldSession(uint32_t sessionId, bool isSoftReset) 218cc290419Sopenharmony_ci{ 219cc290419Sopenharmony_ci HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(clsMainBase); 220cc290419Sopenharmony_ci if (sessionId == 0) { 221cc290419Sopenharmony_ci sessionId = currentSessionId; 222cc290419Sopenharmony_ci } 223cc290419Sopenharmony_ci HSession hSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); 224cc290419Sopenharmony_ci if (hSession == nullptr) { 225cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ResetOldSession hSession nullptr sessionId:%u", sessionId); 226cc290419Sopenharmony_ci return; 227cc290419Sopenharmony_ci } 228cc290419Sopenharmony_ci // The Host side is restarted, but the USB cable is still connected 229cc290419Sopenharmony_ci hSession->isSoftReset = isSoftReset; 230cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Hostside softreset to restart daemon, old sessionId:%u isSoftReset:%d", 231cc290419Sopenharmony_ci sessionId, isSoftReset); 232cc290419Sopenharmony_ci daemon->FreeSession(sessionId); 233cc290419Sopenharmony_ci} 234cc290419Sopenharmony_ci 235cc290419Sopenharmony_ci// Prevent other USB data misfortunes to send the program crash 236cc290419Sopenharmony_ciint HdcDaemonUSB::AvailablePacket(uint8_t *ioBuf, int ioBytes, uint32_t *sessionId) 237cc290419Sopenharmony_ci{ 238cc290419Sopenharmony_ci int ret = RET_SUCCESS; 239cc290419Sopenharmony_ci while (true) { 240cc290419Sopenharmony_ci if (!IsUsbPacketHeader(ioBuf, ioBytes)) { 241cc290419Sopenharmony_ci break; 242cc290419Sopenharmony_ci } 243cc290419Sopenharmony_ci // usb header 244cc290419Sopenharmony_ci USBHead *usbPayloadHeader = reinterpret_cast<struct USBHead *>(ioBuf); 245cc290419Sopenharmony_ci uint32_t inSessionId = ntohl(usbPayloadHeader->sessionId); 246cc290419Sopenharmony_ci if ((usbPayloadHeader->option & USB_OPTION_RESET)) { 247cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "USB_OPTION_RESET inSessionId:%u, currentSessionId:%u", 248cc290419Sopenharmony_ci inSessionId, currentSessionId); 249cc290419Sopenharmony_ci ResetOldSession(inSessionId, true); 250cc290419Sopenharmony_ci ret = ERR_IO_SOFT_RESET; 251cc290419Sopenharmony_ci break; 252cc290419Sopenharmony_ci } 253cc290419Sopenharmony_ci *sessionId = inSessionId; 254cc290419Sopenharmony_ci break; 255cc290419Sopenharmony_ci } 256cc290419Sopenharmony_ci return ret; 257cc290419Sopenharmony_ci} 258cc290419Sopenharmony_ci 259cc290419Sopenharmony_ci// Work in subcrete,Work thread is ready 260cc290419Sopenharmony_cibool HdcDaemonUSB::ReadyForWorkThread(HSession hSession) 261cc290419Sopenharmony_ci{ 262cc290419Sopenharmony_ci HdcUSBBase::ReadyForWorkThread(hSession); 263cc290419Sopenharmony_ci return true; 264cc290419Sopenharmony_ci}; 265cc290419Sopenharmony_ci 266cc290419Sopenharmony_ciint HdcDaemonUSB::CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop) 267cc290419Sopenharmony_ci{ 268cc290419Sopenharmony_ci struct CtxCloseBulkEp { 269cc290419Sopenharmony_ci uv_fs_t req; 270cc290419Sopenharmony_ci HdcDaemonUSB *thisClass; 271cc290419Sopenharmony_ci bool bulkInOut; 272cc290419Sopenharmony_ci }; 273cc290419Sopenharmony_ci CtxCloseBulkEp *ctx = new(std::nothrow) CtxCloseBulkEp(); 274cc290419Sopenharmony_ci if (ctx == nullptr) { 275cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CloseBulkEp new ctx failed"); 276cc290419Sopenharmony_ci return -1; 277cc290419Sopenharmony_ci } 278cc290419Sopenharmony_ci uv_fs_t *req = &ctx->req; 279cc290419Sopenharmony_ci req->data = ctx; 280cc290419Sopenharmony_ci ctx->bulkInOut = bulkInOut; 281cc290419Sopenharmony_ci ctx->thisClass = this; 282cc290419Sopenharmony_ci isAlive = false; 283cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "CloseBulkEp bulkFd:%d", bulkFd); 284cc290419Sopenharmony_ci uv_fs_close(loop, req, bulkFd, [](uv_fs_t *req) { 285cc290419Sopenharmony_ci auto ctx = (CtxCloseBulkEp *)req->data; 286cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Try to abort blukin write callback %s", ctx->bulkInOut ? "bulkin" : "bulkout"); 287cc290419Sopenharmony_ci if (ctx->bulkInOut) { 288cc290419Sopenharmony_ci ctx->thisClass->usbHandle.bulkIn = 0; 289cc290419Sopenharmony_ci } else { 290cc290419Sopenharmony_ci ctx->thisClass->usbHandle.bulkOut = 0; 291cc290419Sopenharmony_ci } 292cc290419Sopenharmony_ci uv_fs_req_cleanup(req); 293cc290419Sopenharmony_ci delete ctx; 294cc290419Sopenharmony_ci }); 295cc290419Sopenharmony_ci return 0; 296cc290419Sopenharmony_ci} 297cc290419Sopenharmony_ci 298cc290419Sopenharmony_ciint HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t *data, const int length) 299cc290419Sopenharmony_ci{ 300cc290419Sopenharmony_ci int bulkIn = hMainUSB->bulkIn; 301cc290419Sopenharmony_ci int childRet = 0; 302cc290419Sopenharmony_ci int ret = ERR_IO_FAIL; 303cc290419Sopenharmony_ci int offset = 0; 304cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::SendUSBIOSync"); 305cc290419Sopenharmony_ci while (modRunning && isAlive && !hSession->isDead) { 306cc290419Sopenharmony_ci childRet = write(bulkIn, const_cast<uint8_t *>(data) + offset, length - offset); 307cc290419Sopenharmony_ci if (childRet <= 0) { 308cc290419Sopenharmony_ci int err = errno; 309cc290419Sopenharmony_ci if (err == EINTR) { 310cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "BulkinWrite write EINTR, try again, offset:%u bulkIn:%d bulkOut:%d", 311cc290419Sopenharmony_ci offset, bulkIn, hMainUSB->bulkOut); 312cc290419Sopenharmony_ci continue; 313cc290419Sopenharmony_ci } else { 314cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "BulkinWrite write fatal errno %d", err); 315cc290419Sopenharmony_ci isAlive = false; 316cc290419Sopenharmony_ci } 317cc290419Sopenharmony_ci break; 318cc290419Sopenharmony_ci } 319cc290419Sopenharmony_ci offset += childRet; 320cc290419Sopenharmony_ci if (offset >= length) { 321cc290419Sopenharmony_ci break; 322cc290419Sopenharmony_ci } 323cc290419Sopenharmony_ci } 324cc290419Sopenharmony_ci if (offset == length) { 325cc290419Sopenharmony_ci ret = length; 326cc290419Sopenharmony_ci } else { 327cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "BulkinWrite write failed, nsize:%d really:%d modRunning:%d isAlive:%d SessionDead:%d", 328cc290419Sopenharmony_ci length, offset, modRunning, isAlive, hSession->isDead); 329cc290419Sopenharmony_ci } 330cc290419Sopenharmony_ci return ret; 331cc290419Sopenharmony_ci} 332cc290419Sopenharmony_ci 333cc290419Sopenharmony_ciint HdcDaemonUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) 334cc290419Sopenharmony_ci{ 335cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::SendUSBRaw"); 336cc290419Sopenharmony_ci HdcDaemon *daemon = (HdcDaemon *)hSession->classInstance; 337cc290419Sopenharmony_ci uint32_t sessionId = hSession->sessionId; 338cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(mutexUsbFfs); 339cc290419Sopenharmony_ci if (Base::IsSessionDeleted(sessionId)) { 340cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "SendUSBRaw session %u is deleted", sessionId); 341cc290419Sopenharmony_ci return ERR_SESSION_DEAD; 342cc290419Sopenharmony_ci } 343cc290419Sopenharmony_ci ++hSession->ref; 344cc290419Sopenharmony_ci int ret = SendUSBIOSync(hSession, &usbHandle, data, length); 345cc290419Sopenharmony_ci --hSession->ref; 346cc290419Sopenharmony_ci if (ret < 0) { 347cc290419Sopenharmony_ci daemon->FreeSession(hSession->sessionId); 348cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "SendUSBRaw try to freesession"); 349cc290419Sopenharmony_ci } 350cc290419Sopenharmony_ci return ret; 351cc290419Sopenharmony_ci} 352cc290419Sopenharmony_ci 353cc290419Sopenharmony_ci// cross thread call 354cc290419Sopenharmony_civoid HdcDaemonUSB::OnNewHandshakeOK(const uint32_t sessionId) 355cc290419Sopenharmony_ci{ 356cc290419Sopenharmony_ci currentSessionId = sessionId; // sync with server, and set server's real Id 357cc290419Sopenharmony_ci} 358cc290419Sopenharmony_ci 359cc290419Sopenharmony_ci// MainThreadCall, when seession was freed 360cc290419Sopenharmony_civoid HdcDaemonUSB::OnSessionFreeFinally(const HSession hSession) 361cc290419Sopenharmony_ci{ 362cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "OnSessionFreeFinally sid:%u currentsid:%u", hSession->sessionId, currentSessionId); 363cc290419Sopenharmony_ci if (hSession->isSoftReset) { 364cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "OnSessionFreeFinally sid:%u softreset", hSession->sessionId); 365cc290419Sopenharmony_ci return; 366cc290419Sopenharmony_ci } 367cc290419Sopenharmony_ci if (currentSessionId == hSession->sessionId) { 368cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "OnSessionFreeFinally set isAlive false"); 369cc290419Sopenharmony_ci isAlive = false; 370cc290419Sopenharmony_ci // uv_cancel ctxRecv.req == UV_EBUSY, not effect immediately. It must be close by logic 371cc290419Sopenharmony_ci } 372cc290419Sopenharmony_ci} 373cc290419Sopenharmony_ci 374cc290419Sopenharmony_ciHSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO) 375cc290419Sopenharmony_ci{ 376cc290419Sopenharmony_ci HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(clsMainBase); 377cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::PrepareNewSession"); 378cc290419Sopenharmony_ci HSession hChildSession = daemon->MallocSession(false, CONN_USB, this, sessionId); 379cc290419Sopenharmony_ci if (!hChildSession) { 380cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "malloc session failed sessionId:%u", sessionId); 381cc290419Sopenharmony_ci return nullptr; 382cc290419Sopenharmony_ci } 383cc290419Sopenharmony_ci currentSessionId = sessionId; 384cc290419Sopenharmony_ci Base::StartWorkThread(&daemon->loopMain, daemon->SessionWorkThread, Base::FinishWorkThread, hChildSession); 385cc290419Sopenharmony_ci 386cc290419Sopenharmony_ci HSessionInfo hSessionInfo = new(std::nothrow) HdcSessionInfo(); 387cc290419Sopenharmony_ci if (hSessionInfo == nullptr) { 388cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "PrepareNewSession new hSessionInfo failed"); 389cc290419Sopenharmony_ci return nullptr; 390cc290419Sopenharmony_ci } 391cc290419Sopenharmony_ci hSessionInfo->sessionId = hChildSession->sessionId; 392cc290419Sopenharmony_ci hSessionInfo->classInstance = hChildSession->classInstance; 393cc290419Sopenharmony_ci hSessionInfo->classModule = hChildSession->classModule; 394cc290419Sopenharmony_ci hSessionInfo->hSession = hChildSession; 395cc290419Sopenharmony_ci auto funcNewSessionUp = [](uv_timer_t *handle) -> void { 396cc290419Sopenharmony_ci HSessionInfo hSessionInfo = reinterpret_cast<HSessionInfo>(handle->data); 397cc290419Sopenharmony_ci if (hSessionInfo == nullptr) { 398cc290419Sopenharmony_ci Base::TryCloseHandle(reinterpret_cast<uv_handle_t *>(handle), Base::CloseTimerCallback); 399cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "hSessionInfo is null"); 400cc290419Sopenharmony_ci return; 401cc290419Sopenharmony_ci } 402cc290419Sopenharmony_ci HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(hSessionInfo->classInstance); 403cc290419Sopenharmony_ci if (Base::IsSessionDeleted(hSessionInfo->sessionId)) { 404cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "funcNewSessionUp session is deleted"); 405cc290419Sopenharmony_ci delete hSessionInfo; 406cc290419Sopenharmony_ci handle->data = nullptr; 407cc290419Sopenharmony_ci Base::TryCloseHandle(reinterpret_cast<uv_handle_t *>(handle), Base::CloseTimerCallback); 408cc290419Sopenharmony_ci return; 409cc290419Sopenharmony_ci } 410cc290419Sopenharmony_ci HSession hChildSession = hSessionInfo->hSession; 411cc290419Sopenharmony_ci if (hChildSession->childLoop.active_handles == 0) { 412cc290419Sopenharmony_ci return; 413cc290419Sopenharmony_ci } 414cc290419Sopenharmony_ci if (!hChildSession->isDead) { 415cc290419Sopenharmony_ci auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); 416cc290419Sopenharmony_ci Base::SendToPollFd(hChildSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size()); 417cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Main thread usbio migrate finish"); 418cc290419Sopenharmony_ci } 419cc290419Sopenharmony_ci delete hSessionInfo; 420cc290419Sopenharmony_ci handle->data = nullptr; 421cc290419Sopenharmony_ci Base::TryCloseHandle(reinterpret_cast<uv_handle_t *>(handle), Base::CloseTimerCallback); 422cc290419Sopenharmony_ci }; 423cc290419Sopenharmony_ci Base::TimerUvTask(&daemon->loopMain, hSessionInfo, funcNewSessionUp); 424cc290419Sopenharmony_ci return hChildSession; 425cc290419Sopenharmony_ci} 426cc290419Sopenharmony_ci 427cc290419Sopenharmony_civoid HdcDaemonUSB::UvWriteCallback(uv_write_t *req, int status) 428cc290419Sopenharmony_ci{ 429cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::UvWriteCallback"); 430cc290419Sopenharmony_ci if (status < 0) { 431cc290419Sopenharmony_ci constexpr int bufSize = 1024; 432cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 433cc290419Sopenharmony_ci uv_strerror_r(status, buf, bufSize); 434cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "SendCallback failed,status:%d %s", status, buf); 435cc290419Sopenharmony_ci } 436cc290419Sopenharmony_ci UvData *uvData = reinterpret_cast<UvData *>(req->data); 437cc290419Sopenharmony_ci if (uvData) { 438cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 439cc290419Sopenharmony_ci uvData->daemonUsb->cirbuf.Free(uvData->buf); 440cc290419Sopenharmony_ci#else 441cc290419Sopenharmony_ci delete[] uvData->buf; 442cc290419Sopenharmony_ci#endif 443cc290419Sopenharmony_ci delete uvData; 444cc290419Sopenharmony_ci } 445cc290419Sopenharmony_ci delete req; 446cc290419Sopenharmony_ci} 447cc290419Sopenharmony_ci 448cc290419Sopenharmony_ciint HdcDaemonUSB::UsbToStream(uv_stream_t *stream, const uint8_t *buf, const int size) 449cc290419Sopenharmony_ci{ 450cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::UsbToStream"); 451cc290419Sopenharmony_ci int ret = ERR_GENERIC; 452cc290419Sopenharmony_ci uv_write_t *reqWrite = new uv_write_t(); 453cc290419Sopenharmony_ci if (!reqWrite) { 454cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UsbToStream new write_t failed size:%d", size); 455cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 456cc290419Sopenharmony_ci cirbuf.Free(buf); 457cc290419Sopenharmony_ci#else 458cc290419Sopenharmony_ci delete[] buf; 459cc290419Sopenharmony_ci#endif 460cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 461cc290419Sopenharmony_ci } 462cc290419Sopenharmony_ci uv_buf_t bfr; 463cc290419Sopenharmony_ci while (true) { 464cc290419Sopenharmony_ci UvData *uvData = new(std::nothrow) UvData(); 465cc290419Sopenharmony_ci if (uvData == nullptr) { 466cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "UsbToStream new uvData failed size:%d", size); 467cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 468cc290419Sopenharmony_ci cirbuf.Free(buf); 469cc290419Sopenharmony_ci#else 470cc290419Sopenharmony_ci delete[] buf; 471cc290419Sopenharmony_ci#endif 472cc290419Sopenharmony_ci delete reqWrite; 473cc290419Sopenharmony_ci return ERR_BUF_ALLOC; 474cc290419Sopenharmony_ci } 475cc290419Sopenharmony_ci uvData->daemonUsb = this; 476cc290419Sopenharmony_ci uvData->buf = buf; 477cc290419Sopenharmony_ci reqWrite->data = reinterpret_cast<void *>(uvData); 478cc290419Sopenharmony_ci bfr.base = (char *)buf; 479cc290419Sopenharmony_ci bfr.len = size; 480cc290419Sopenharmony_ci if (!uv_is_writable(stream)) { 481cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UsbToStream uv_is_writable false size:%d", size); 482cc290419Sopenharmony_ci delete reqWrite; 483cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 484cc290419Sopenharmony_ci cirbuf.Free(buf); 485cc290419Sopenharmony_ci#else 486cc290419Sopenharmony_ci delete[] buf; 487cc290419Sopenharmony_ci#endif 488cc290419Sopenharmony_ci delete uvData; 489cc290419Sopenharmony_ci break; 490cc290419Sopenharmony_ci } 491cc290419Sopenharmony_ci ret = uv_write(reqWrite, stream, &bfr, 1, UvWriteCallback); 492cc290419Sopenharmony_ci if (ret < 0) { 493cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UsbToStream uv_write false ret:%d", ret); 494cc290419Sopenharmony_ci delete reqWrite; 495cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 496cc290419Sopenharmony_ci cirbuf.Free(buf); 497cc290419Sopenharmony_ci#else 498cc290419Sopenharmony_ci delete[] buf; 499cc290419Sopenharmony_ci#endif 500cc290419Sopenharmony_ci delete uvData; 501cc290419Sopenharmony_ci ret = ERR_IO_FAIL; 502cc290419Sopenharmony_ci break; 503cc290419Sopenharmony_ci } 504cc290419Sopenharmony_ci ret = size; 505cc290419Sopenharmony_ci break; 506cc290419Sopenharmony_ci } 507cc290419Sopenharmony_ci return ret; 508cc290419Sopenharmony_ci} 509cc290419Sopenharmony_ci 510cc290419Sopenharmony_ciint HdcDaemonUSB::UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int dataSize) 511cc290419Sopenharmony_ci{ 512cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::UsbToHdcProtocol"); 513cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 514cc290419Sopenharmony_ci uint8_t *data = cirbuf.Malloc(); 515cc290419Sopenharmony_ci#else 516cc290419Sopenharmony_ci uint8_t *data = new uint8_t[dataSize]; 517cc290419Sopenharmony_ci#endif 518cc290419Sopenharmony_ci if (data == nullptr) { 519cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UsbToHdcProtocol data nullptr"); 520cc290419Sopenharmony_ci return -1; 521cc290419Sopenharmony_ci } 522cc290419Sopenharmony_ci if (memcpy_s(data, dataSize, appendData, dataSize)) { 523cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "UsbToHdcProtocol memory copy failed dataSize:%d", dataSize); 524cc290419Sopenharmony_ci#ifndef CONFIG_USE_JEMALLOC_DFX_INIF 525cc290419Sopenharmony_ci cirbuf.Free(data); 526cc290419Sopenharmony_ci#else 527cc290419Sopenharmony_ci delete[] data; 528cc290419Sopenharmony_ci#endif 529cc290419Sopenharmony_ci return ERR_BUF_COPY; 530cc290419Sopenharmony_ci } 531cc290419Sopenharmony_ci return UsbToStream(stream, data, dataSize); 532cc290419Sopenharmony_ci} 533cc290419Sopenharmony_ci 534cc290419Sopenharmony_ciint HdcDaemonUSB::DispatchToWorkThread(uint32_t sessionId, uint8_t *readBuf, int readBytes) 535cc290419Sopenharmony_ci{ 536cc290419Sopenharmony_ci HSession hChildSession = nullptr; 537cc290419Sopenharmony_ci HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(clsMainBase); 538cc290419Sopenharmony_ci int childRet = RET_SUCCESS; 539cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::DispatchToWorkThread"); 540cc290419Sopenharmony_ci if (sessionId == 0) { 541cc290419Sopenharmony_ci // hdc packet data 542cc290419Sopenharmony_ci sessionId = currentSessionId; 543cc290419Sopenharmony_ci } 544cc290419Sopenharmony_ci if (currentSessionId != 0 && sessionId != currentSessionId) { 545cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "New session coming, restart old sessionId:%u", currentSessionId); 546cc290419Sopenharmony_ci ResetOldSession(currentSessionId); 547cc290419Sopenharmony_ci currentSessionId = 0; 548cc290419Sopenharmony_ci } 549cc290419Sopenharmony_ci hChildSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); 550cc290419Sopenharmony_ci if (!hChildSession) { 551cc290419Sopenharmony_ci hChildSession = PrepareNewSession(sessionId, readBuf, readBytes); 552cc290419Sopenharmony_ci if (!hChildSession) { 553cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "prep new session err for sessionId:%u", sessionId); 554cc290419Sopenharmony_ci return ERR_SESSION_NOFOUND; 555cc290419Sopenharmony_ci } 556cc290419Sopenharmony_ci } 557cc290419Sopenharmony_ci 558cc290419Sopenharmony_ci if (hChildSession->childCleared || hChildSession->isDead) { 559cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "session dead clr:%d - %d", hChildSession->childCleared, hChildSession->isDead); 560cc290419Sopenharmony_ci return ERR_SESSION_DEAD; 561cc290419Sopenharmony_ci } 562cc290419Sopenharmony_ci uv_stream_t *stream = reinterpret_cast<uv_stream_t *>(&hChildSession->dataPipe[STREAM_MAIN]); 563cc290419Sopenharmony_ci if ((childRet = SendToHdcStream(hChildSession, stream, readBuf, readBytes)) < 0) { 564cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "DispatchToWorkThread SendToHdcStream err ret:%d", childRet); 565cc290419Sopenharmony_ci return ERR_IO_FAIL; 566cc290419Sopenharmony_ci } 567cc290419Sopenharmony_ci return childRet; 568cc290419Sopenharmony_ci} 569cc290419Sopenharmony_ci 570cc290419Sopenharmony_cibool HdcDaemonUSB::JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const 571cc290419Sopenharmony_ci{ 572cc290419Sopenharmony_ci constexpr size_t antiqueFlagSize = 4; 573cc290419Sopenharmony_ci constexpr size_t antiqueFullSize = 24; 574cc290419Sopenharmony_ci // anti CNXN 0x4e584e43 575cc290419Sopenharmony_ci uint8_t flag[] = { 0x43, 0x4e, 0x58, 0x4e }; 576cc290419Sopenharmony_ci if (bytes == antiqueFullSize && !memcmp(&buf, flag, antiqueFlagSize)) { 577cc290419Sopenharmony_ci return true; 578cc290419Sopenharmony_ci } 579cc290419Sopenharmony_ci return false; 580cc290419Sopenharmony_ci} 581cc290419Sopenharmony_ci 582cc290419Sopenharmony_ci// Only physically swap EP ports will be reset 583cc290419Sopenharmony_civoid HdcDaemonUSB::OnUSBRead(uv_fs_t *req) 584cc290419Sopenharmony_ci{ // Only read at the main thread 585cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::OnUSBRead"); 586cc290419Sopenharmony_ci auto ctxIo = reinterpret_cast<CtxUvFileCommonIo *>(req->data); 587cc290419Sopenharmony_ci auto hUSB = reinterpret_cast<HUSB>(ctxIo->data); 588cc290419Sopenharmony_ci auto thisClass = reinterpret_cast<HdcDaemonUSB *>(ctxIo->thisClass); 589cc290419Sopenharmony_ci uint8_t *bufPtr = ctxIo->buf; 590cc290419Sopenharmony_ci ssize_t bytesIOBytes = req->result; 591cc290419Sopenharmony_ci uint32_t sessionId = 0; 592cc290419Sopenharmony_ci bool ret = false; 593cc290419Sopenharmony_ci int childRet = 0; 594cc290419Sopenharmony_ci if (bytesIOBytes > hUSB->wMaxPacketSizeSend && bytesIOBytes != thisClass->saveNextReadSize) { 595cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Not full packet, wanted:%d really:%d", thisClass->saveNextReadSize, bytesIOBytes); 596cc290419Sopenharmony_ci } 597cc290419Sopenharmony_ci while (thisClass->isAlive) { 598cc290419Sopenharmony_ci // Don't care is module running, first deal with this 599cc290419Sopenharmony_ci if (bytesIOBytes < 0) { 600cc290419Sopenharmony_ci // logic alive and EINTER is gdb attach 601cc290419Sopenharmony_ci // 602cc290419Sopenharmony_ci // [about gdb attach known issue] 603cc290419Sopenharmony_ci // When GDB debugging is loaded, the number of USB read interrupts of libuv will increase. Multiple 604cc290419Sopenharmony_ci // interrupts will increase the correctness of USB data reading. Setting GDB to asynchronous mode or using 605cc290419Sopenharmony_ci // log debugging can avoid this problem 606cc290419Sopenharmony_ci if (bytesIOBytes != -EINTR) { // Epoll will be broken when gdb attach 607cc290419Sopenharmony_ci constexpr int bufSize = 1024; 608cc290419Sopenharmony_ci char buf[bufSize] = { 0 }; 609cc290419Sopenharmony_ci uv_strerror_r(bytesIOBytes, buf, bufSize); 610cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "USBIO ret:%d failed:%s", bytesIOBytes, buf); 611cc290419Sopenharmony_ci ret = false; 612cc290419Sopenharmony_ci break; 613cc290419Sopenharmony_ci } else { 614cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "OnUSBRead signal EINTR"); 615cc290419Sopenharmony_ci } 616cc290419Sopenharmony_ci } else if (bytesIOBytes == 0) { // zero packet 617cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "Zero packet received"); 618cc290419Sopenharmony_ci } else { 619cc290419Sopenharmony_ci if (thisClass->JumpAntiquePacket(*bufPtr, bytesIOBytes)) { 620cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "JumpAntiquePacket auto jump"); 621cc290419Sopenharmony_ci ret = true; 622cc290419Sopenharmony_ci break; 623cc290419Sopenharmony_ci } 624cc290419Sopenharmony_ci // guess is head of packet 625cc290419Sopenharmony_ci if ((childRet = thisClass->AvailablePacket((uint8_t *)bufPtr, bytesIOBytes, &sessionId)) != RET_SUCCESS) { 626cc290419Sopenharmony_ci if (childRet != ERR_IO_SOFT_RESET) { 627cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "AvailablePacket check failed, ret:%d buf:%-50s", bytesIOBytes, bufPtr); 628cc290419Sopenharmony_ci break; 629cc290419Sopenharmony_ci } 630cc290419Sopenharmony_ci // reset packet 631cc290419Sopenharmony_ci childRet = 0; // need max size 632cc290419Sopenharmony_ci } else { 633cc290419Sopenharmony_ci // AvailablePacket case 634cc290419Sopenharmony_ci if ((childRet = thisClass->DispatchToWorkThread(sessionId, bufPtr, bytesIOBytes)) < 0) { 635cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "DispatchToWorkThread failed"); 636cc290419Sopenharmony_ci break; 637cc290419Sopenharmony_ci } 638cc290419Sopenharmony_ci } 639cc290419Sopenharmony_ci } 640cc290419Sopenharmony_ci int nextReadSize = childRet == 0 ? hUSB->wMaxPacketSizeSend : std::min(childRet, Base::GetUsbffsBulkSize()); 641cc290419Sopenharmony_ci thisClass->saveNextReadSize = nextReadSize; 642cc290419Sopenharmony_ci if (thisClass->LoopUSBRead(hUSB, nextReadSize) < 0) { 643cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "LoopUSBRead failed"); 644cc290419Sopenharmony_ci break; 645cc290419Sopenharmony_ci } 646cc290419Sopenharmony_ci ret = true; 647cc290419Sopenharmony_ci break; 648cc290419Sopenharmony_ci } 649cc290419Sopenharmony_ci if (!ret) { 650cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "OnUSBRead ret false, set isAlive = false"); 651cc290419Sopenharmony_ci thisClass->isAlive = false; 652cc290419Sopenharmony_ci thisClass->ctxRecv.atPollQueue = false; 653cc290419Sopenharmony_ci } 654cc290419Sopenharmony_ci} 655cc290419Sopenharmony_ci 656cc290419Sopenharmony_ciint HdcDaemonUSB::LoopUSBRead(HUSB hUSB, int readMaxWanted) 657cc290419Sopenharmony_ci{ 658cc290419Sopenharmony_ci StartTraceScope("HdcDaemonUSB::LoopUSBRead"); 659cc290419Sopenharmony_ci int ret = ERR_GENERIC; 660cc290419Sopenharmony_ci HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(clsMainBase); 661cc290419Sopenharmony_ci if (daemon == nullptr) { 662cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "daemon is nullptr in LoopUSBRead"); 663cc290419Sopenharmony_ci return ret; 664cc290419Sopenharmony_ci } 665cc290419Sopenharmony_ci uv_buf_t iov; 666cc290419Sopenharmony_ci ctxRecv.data = hUSB; 667cc290419Sopenharmony_ci ctxRecv.bufSize = readMaxWanted; 668cc290419Sopenharmony_ci ctxRecv.req = {}; 669cc290419Sopenharmony_ci uv_fs_t *req = &ctxRecv.req; 670cc290419Sopenharmony_ci req->data = &ctxRecv; 671cc290419Sopenharmony_ci iov = uv_buf_init(reinterpret_cast<char *>(ctxRecv.buf), ctxRecv.bufSize); 672cc290419Sopenharmony_ci ret = uv_fs_read(&daemon->loopMain, req, hUSB->bulkOut, &iov, 1, -1, OnUSBRead); 673cc290419Sopenharmony_ci if (ret < 0) { 674cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "uv_fs_read ret:%d < 0", ret); 675cc290419Sopenharmony_ci return ERR_API_FAIL; 676cc290419Sopenharmony_ci } 677cc290419Sopenharmony_ci ctxRecv.atPollQueue = true; 678cc290419Sopenharmony_ci return RET_SUCCESS; 679cc290419Sopenharmony_ci} 680cc290419Sopenharmony_ci 681cc290419Sopenharmony_ci// Because USB can connect to only one host,daemonUSB is only one Session by default 682cc290419Sopenharmony_civoid HdcDaemonUSB::WatchEPTimer(uv_timer_t *handle) 683cc290419Sopenharmony_ci{ 684cc290419Sopenharmony_ci HdcDaemonUSB *thisClass = (HdcDaemonUSB *)handle->data; 685cc290419Sopenharmony_ci HUSB hUSB = &thisClass->usbHandle; 686cc290419Sopenharmony_ci HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(thisClass->clsMainBase); 687cc290419Sopenharmony_ci if (thisClass->isAlive || thisClass->ctxRecv.atPollQueue) { 688cc290419Sopenharmony_ci return; 689cc290419Sopenharmony_ci } 690cc290419Sopenharmony_ci bool resetEp = false; 691cc290419Sopenharmony_ci do { 692cc290419Sopenharmony_ci if (hUSB->bulkIn > 0) { 693cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Watchdog close bulkin"); 694cc290419Sopenharmony_ci thisClass->CloseBulkEp(true, thisClass->usbHandle.bulkIn, &daemon->loopMain); 695cc290419Sopenharmony_ci resetEp = true; 696cc290419Sopenharmony_ci } 697cc290419Sopenharmony_ci if (hUSB->bulkOut > 0) { 698cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Watchdog close bulkout"); 699cc290419Sopenharmony_ci thisClass->CloseBulkEp(false, thisClass->usbHandle.bulkOut, &daemon->loopMain); 700cc290419Sopenharmony_ci resetEp = true; 701cc290419Sopenharmony_ci } 702cc290419Sopenharmony_ci if (thisClass->controlEp > 0) { 703cc290419Sopenharmony_ci Base::CloseFd(thisClass->controlEp); 704cc290419Sopenharmony_ci resetEp = true; 705cc290419Sopenharmony_ci } 706cc290419Sopenharmony_ci } while (false); 707cc290419Sopenharmony_ci if (resetEp || thisClass->usbHandle.bulkIn != 0 || thisClass->usbHandle.bulkOut != 0) { 708cc290419Sopenharmony_ci return; 709cc290419Sopenharmony_ci } 710cc290419Sopenharmony_ci // until all bulkport reset 711cc290419Sopenharmony_ci if (thisClass->ConnectEPPoint(hUSB) != RET_SUCCESS) { 712cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "WatchEPTimer ConnectEPPoint failed"); 713cc290419Sopenharmony_ci return; 714cc290419Sopenharmony_ci } 715cc290419Sopenharmony_ci // connect OK 716cc290419Sopenharmony_ci thisClass->isAlive = true; 717cc290419Sopenharmony_ci thisClass->LoopUSBRead(hUSB, hUSB->wMaxPacketSizeSend); 718cc290419Sopenharmony_ci} 719cc290419Sopenharmony_ci} // namespace Hdc 720