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 "host_usb.h" 16cc290419Sopenharmony_ci#include <stdlib.h> 17cc290419Sopenharmony_ci#include <thread> 18cc290419Sopenharmony_ci 19cc290419Sopenharmony_ci#include "server.h" 20cc290419Sopenharmony_cinamespace Hdc { 21cc290419Sopenharmony_ciHdcHostUSB::HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin) 22cc290419Sopenharmony_ci : HdcUSBBase(serverOrDaemonIn, ptrMainBase) 23cc290419Sopenharmony_ci{ 24cc290419Sopenharmony_ci modRunning = false; 25cc290419Sopenharmony_ci HdcServer *pServer = (HdcServer *)ptrMainBase; 26cc290419Sopenharmony_ci ctxUSB = (libusb_context *)ctxUSBin; 27cc290419Sopenharmony_ci uv_timer_init(&pServer->loopMain, &devListWatcher); 28cc290419Sopenharmony_ci} 29cc290419Sopenharmony_ci 30cc290419Sopenharmony_ciHdcHostUSB::~HdcHostUSB() 31cc290419Sopenharmony_ci{ 32cc290419Sopenharmony_ci if (modRunning) { 33cc290419Sopenharmony_ci Stop(); 34cc290419Sopenharmony_ci } 35cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "~HdcHostUSB"); 36cc290419Sopenharmony_ci} 37cc290419Sopenharmony_ci 38cc290419Sopenharmony_civoid HdcHostUSB::Stop() 39cc290419Sopenharmony_ci{ 40cc290419Sopenharmony_ci if (!ctxUSB) { 41cc290419Sopenharmony_ci return; 42cc290419Sopenharmony_ci } 43cc290419Sopenharmony_ci Base::TryCloseHandle((uv_handle_t *)&devListWatcher); 44cc290419Sopenharmony_ci modRunning = false; 45cc290419Sopenharmony_ci} 46cc290419Sopenharmony_ci 47cc290419Sopenharmony_ciint HdcHostUSB::Initial() 48cc290419Sopenharmony_ci{ 49cc290419Sopenharmony_ci if (!ctxUSB) { 50cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "USB mod ctxUSB is nullptr, recompile please"); 51cc290419Sopenharmony_ci return -1; 52cc290419Sopenharmony_ci } 53cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcHostUSB init"); 54cc290419Sopenharmony_ci modRunning = true; 55cc290419Sopenharmony_ci StartupUSBWork(); // Main thread registration, IO in sub-thread 56cc290419Sopenharmony_ci return 0; 57cc290419Sopenharmony_ci} 58cc290419Sopenharmony_ci 59cc290419Sopenharmony_cistatic void UsbLogHandler(libusb_context* ctx, enum libusb_log_level level, const char* str) 60cc290419Sopenharmony_ci{ 61cc290419Sopenharmony_ci int l = -1; 62cc290419Sopenharmony_ci switch (level) { 63cc290419Sopenharmony_ci case LIBUSB_LOG_LEVEL_ERROR: 64cc290419Sopenharmony_ci l = LOG_FATAL; 65cc290419Sopenharmony_ci break; 66cc290419Sopenharmony_ci case LIBUSB_LOG_LEVEL_WARNING: 67cc290419Sopenharmony_ci l = LOG_WARN; 68cc290419Sopenharmony_ci break; 69cc290419Sopenharmony_ci case LIBUSB_LOG_LEVEL_INFO: 70cc290419Sopenharmony_ci l = LOG_INFO; 71cc290419Sopenharmony_ci break; 72cc290419Sopenharmony_ci case LIBUSB_LOG_LEVEL_DEBUG: 73cc290419Sopenharmony_ci l = LOG_DEBUG; 74cc290419Sopenharmony_ci break; 75cc290419Sopenharmony_ci default: 76cc290419Sopenharmony_ci break; 77cc290419Sopenharmony_ci } 78cc290419Sopenharmony_ci if (l >= 0) { 79cc290419Sopenharmony_ci char *newStr = strdup(str); 80cc290419Sopenharmony_ci if (!newStr) { 81cc290419Sopenharmony_ci return; 82cc290419Sopenharmony_ci } 83cc290419Sopenharmony_ci char *p = strstr(newStr, "libusb:"); 84cc290419Sopenharmony_ci if (!p) { 85cc290419Sopenharmony_ci p = newStr; 86cc290419Sopenharmony_ci } 87cc290419Sopenharmony_ci char *q = strrchr(newStr, '\n'); 88cc290419Sopenharmony_ci if (q) { 89cc290419Sopenharmony_ci *q = '\0'; 90cc290419Sopenharmony_ci } 91cc290419Sopenharmony_ci WRITE_LOG(l, "%s", p); 92cc290419Sopenharmony_ci free(newStr); 93cc290419Sopenharmony_ci } 94cc290419Sopenharmony_ci} 95cc290419Sopenharmony_civoid HdcHostUSB::InitLogging(void *ctxUSB) 96cc290419Sopenharmony_ci{ 97cc290419Sopenharmony_ci if (ctxUSB == nullptr) { 98cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "InitLogging failed ctxUSB is nullptr"); 99cc290419Sopenharmony_ci return; 100cc290419Sopenharmony_ci } 101cc290419Sopenharmony_ci std::string debugEnv = "LIBUSB_DEBUG"; 102cc290419Sopenharmony_ci libusb_log_level debugLevel; 103cc290419Sopenharmony_ci 104cc290419Sopenharmony_ci switch (static_cast<Hdc::HdcLogLevel>(Base::GetLogLevel())) { 105cc290419Sopenharmony_ci case LOG_WARN: 106cc290419Sopenharmony_ci debugLevel = LIBUSB_LOG_LEVEL_ERROR; 107cc290419Sopenharmony_ci break; 108cc290419Sopenharmony_ci case LOG_INFO: 109cc290419Sopenharmony_ci debugLevel = LIBUSB_LOG_LEVEL_WARNING; 110cc290419Sopenharmony_ci break; 111cc290419Sopenharmony_ci case LOG_DEBUG: 112cc290419Sopenharmony_ci debugLevel = LIBUSB_LOG_LEVEL_INFO; 113cc290419Sopenharmony_ci break; 114cc290419Sopenharmony_ci case LOG_VERBOSE: 115cc290419Sopenharmony_ci debugLevel = LIBUSB_LOG_LEVEL_DEBUG; 116cc290419Sopenharmony_ci break; 117cc290419Sopenharmony_ci case LOG_FATAL: 118cc290419Sopenharmony_ci // pass through to no libusb logging 119cc290419Sopenharmony_ci default: 120cc290419Sopenharmony_ci debugLevel = LIBUSB_LOG_LEVEL_NONE; 121cc290419Sopenharmony_ci break; 122cc290419Sopenharmony_ci } 123cc290419Sopenharmony_ci 124cc290419Sopenharmony_ci libusb_set_option((libusb_context *)ctxUSB, LIBUSB_OPTION_LOG_LEVEL, debugLevel); 125cc290419Sopenharmony_ci libusb_set_log_cb((libusb_context *)ctxUSB, UsbLogHandler, 126cc290419Sopenharmony_ci LIBUSB_LOG_CB_CONTEXT | LIBUSB_LOG_CB_GLOBAL); 127cc290419Sopenharmony_ci 128cc290419Sopenharmony_ci#ifdef _WIN32 129cc290419Sopenharmony_ci debugEnv += "="; 130cc290419Sopenharmony_ci debugEnv += std::to_string(debugLevel); 131cc290419Sopenharmony_ci _putenv(debugEnv.c_str()); 132cc290419Sopenharmony_ci#else 133cc290419Sopenharmony_ci setenv(debugEnv.c_str(), std::to_string(debugLevel).c_str(), 1); 134cc290419Sopenharmony_ci#endif 135cc290419Sopenharmony_ci} 136cc290419Sopenharmony_ci 137cc290419Sopenharmony_cibool HdcHostUSB::DetectMyNeed(libusb_device *device, string &sn) 138cc290419Sopenharmony_ci{ 139cc290419Sopenharmony_ci HUSB hUSB = new(std::nothrow) HdcUSB(); 140cc290419Sopenharmony_ci if (hUSB == nullptr) { 141cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "DetectMyNeed new hUSB failed"); 142cc290419Sopenharmony_ci return false; 143cc290419Sopenharmony_ci } 144cc290419Sopenharmony_ci hUSB->device = device; 145cc290419Sopenharmony_ci // just get usb SN, close handle immediately 146cc290419Sopenharmony_ci int childRet = OpenDeviceMyNeed(hUSB); 147cc290419Sopenharmony_ci if (childRet < 0) { 148cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "DetectMyNeed OpenDeviceMyNeed childRet:%d", childRet); 149cc290419Sopenharmony_ci delete hUSB; 150cc290419Sopenharmony_ci return false; 151cc290419Sopenharmony_ci } 152cc290419Sopenharmony_ci libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber); 153cc290419Sopenharmony_ci libusb_close(hUSB->devHandle); 154cc290419Sopenharmony_ci hUSB->devHandle = nullptr; 155cc290419Sopenharmony_ci 156cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "Needed device found, busid:%d devid:%d connectkey:%s", hUSB->busId, hUSB->devId, 157cc290419Sopenharmony_ci Hdc::MaskString(hUSB->serialNumber).c_str()); 158cc290419Sopenharmony_ci // USB device is automatically connected after recognition, auto connect USB 159cc290419Sopenharmony_ci UpdateUSBDaemonInfo(hUSB, nullptr, STATUS_READY); 160cc290419Sopenharmony_ci HdcServer *hdcServer = (HdcServer *)clsMainBase; 161cc290419Sopenharmony_ci HSession hSession = hdcServer->MallocSession(true, CONN_USB, this); 162cc290419Sopenharmony_ci if (!hSession) { 163cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "malloc usb session failed sn:%s", Hdc::MaskString(sn).c_str()); 164cc290419Sopenharmony_ci return false; 165cc290419Sopenharmony_ci } 166cc290419Sopenharmony_ci hSession->connectKey = hUSB->serialNumber; 167cc290419Sopenharmony_ci uv_timer_t *waitTimeDoCmd = new(std::nothrow) uv_timer_t; 168cc290419Sopenharmony_ci if (waitTimeDoCmd == nullptr) { 169cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "DetectMyNeed new waitTimeDoCmd failed"); 170cc290419Sopenharmony_ci delete hUSB; 171cc290419Sopenharmony_ci hdcServer->FreeSession(hSession->sessionId); 172cc290419Sopenharmony_ci return false; 173cc290419Sopenharmony_ci } 174cc290419Sopenharmony_ci uv_timer_init(&hdcServer->loopMain, waitTimeDoCmd); 175cc290419Sopenharmony_ci waitTimeDoCmd->data = hSession; 176cc290419Sopenharmony_ci uv_timer_start(waitTimeDoCmd, hdcServer->UsbPreConnect, 0, DEVICE_CHECK_INTERVAL); 177cc290419Sopenharmony_ci mapIgnoreDevice[sn] = HOST_USB_REGISTER; 178cc290419Sopenharmony_ci delete hUSB; 179cc290419Sopenharmony_ci return true; 180cc290419Sopenharmony_ci} 181cc290419Sopenharmony_ci 182cc290419Sopenharmony_civoid HdcHostUSB::KickoutZombie(HSession hSession) 183cc290419Sopenharmony_ci{ 184cc290419Sopenharmony_ci HdcServer *ptrConnect = (HdcServer *)hSession->classInstance; 185cc290419Sopenharmony_ci HUSB hUSB = hSession->hUSB; 186cc290419Sopenharmony_ci if (!hUSB->devHandle) { 187cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "KickoutZombie devHandle:%p isDead:%d", hUSB->devHandle, hSession->isDead); 188cc290419Sopenharmony_ci return; 189cc290419Sopenharmony_ci } 190cc290419Sopenharmony_ci if (LIBUSB_ERROR_NO_DEVICE != libusb_kernel_driver_active(hUSB->devHandle, hUSB->interfaceNumber)) { 191cc290419Sopenharmony_ci return; 192cc290419Sopenharmony_ci } 193cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "KickoutZombie LIBUSB_ERROR_NO_DEVICE serialNumber:%s", 194cc290419Sopenharmony_ci Hdc::MaskString(hUSB->serialNumber).c_str()); 195cc290419Sopenharmony_ci ptrConnect->FreeSession(hSession->sessionId); 196cc290419Sopenharmony_ci} 197cc290419Sopenharmony_ci 198cc290419Sopenharmony_civoid HdcHostUSB::RemoveIgnoreDevice(string &mountInfo) 199cc290419Sopenharmony_ci{ 200cc290419Sopenharmony_ci if (mapIgnoreDevice.count(mountInfo)) { 201cc290419Sopenharmony_ci mapIgnoreDevice.erase(mountInfo); 202cc290419Sopenharmony_ci } 203cc290419Sopenharmony_ci} 204cc290419Sopenharmony_ci 205cc290419Sopenharmony_civoid HdcHostUSB::ReviewUsbNodeLater(string &nodeKey) 206cc290419Sopenharmony_ci{ 207cc290419Sopenharmony_ci HdcServer *hdcServer = (HdcServer *)clsMainBase; 208cc290419Sopenharmony_ci // add to ignore list 209cc290419Sopenharmony_ci mapIgnoreDevice[nodeKey] = HOST_USB_IGNORE; 210cc290419Sopenharmony_ci int delayRemoveFromList = DEVICE_CHECK_INTERVAL * MINOR_TIMEOUT; // wait little time for daemon reinit 211cc290419Sopenharmony_ci Base::DelayDo(&hdcServer->loopMain, delayRemoveFromList, 0, nodeKey, nullptr, 212cc290419Sopenharmony_ci [this](const uint8_t flag, string &msg, const void *) -> void { RemoveIgnoreDevice(msg); }); 213cc290419Sopenharmony_ci} 214cc290419Sopenharmony_ci 215cc290419Sopenharmony_civoid HdcHostUSB::WatchUsbNodeChange(uv_timer_t *handle) 216cc290419Sopenharmony_ci{ 217cc290419Sopenharmony_ci HdcHostUSB *thisClass = static_cast<HdcHostUSB *>(handle->data); 218cc290419Sopenharmony_ci HdcServer *ptrConnect = static_cast<HdcServer *>(thisClass->clsMainBase); 219cc290419Sopenharmony_ci libusb_device **devs = nullptr; 220cc290419Sopenharmony_ci libusb_device *dev = nullptr; 221cc290419Sopenharmony_ci // kick zombie 222cc290419Sopenharmony_ci ptrConnect->EnumUSBDeviceRegister(KickoutZombie); 223cc290419Sopenharmony_ci // find new 224cc290419Sopenharmony_ci ssize_t cnt = libusb_get_device_list(thisClass->ctxUSB, &devs); 225cc290419Sopenharmony_ci if (cnt < 0) { 226cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Failed to get device list"); 227cc290419Sopenharmony_ci return; 228cc290419Sopenharmony_ci } 229cc290419Sopenharmony_ci int i = 0; 230cc290419Sopenharmony_ci // linux replug devid increment,windows will be not 231cc290419Sopenharmony_ci while ((dev = devs[i++]) != nullptr) { // must postfix++ 232cc290419Sopenharmony_ci string szTmpKey = Base::StringFormat("%d-%d", libusb_get_bus_number(dev), libusb_get_device_address(dev)); 233cc290419Sopenharmony_ci // check is in ignore list 234cc290419Sopenharmony_ci UsbCheckStatus statusCheck = thisClass->mapIgnoreDevice[szTmpKey]; 235cc290419Sopenharmony_ci if (statusCheck == HOST_USB_IGNORE || statusCheck == HOST_USB_REGISTER) { 236cc290419Sopenharmony_ci continue; 237cc290419Sopenharmony_ci } 238cc290419Sopenharmony_ci string sn = szTmpKey; 239cc290419Sopenharmony_ci if (thisClass->HasValidDevice(dev) && !thisClass->DetectMyNeed(dev, sn)) { 240cc290419Sopenharmony_ci thisClass->ReviewUsbNodeLater(szTmpKey); 241cc290419Sopenharmony_ci } 242cc290419Sopenharmony_ci } 243cc290419Sopenharmony_ci libusb_free_device_list(devs, 1); 244cc290419Sopenharmony_ci} 245cc290419Sopenharmony_ci 246cc290419Sopenharmony_cibool HdcHostUSB::HasValidDevice(libusb_device *device) 247cc290419Sopenharmony_ci{ 248cc290419Sopenharmony_ci struct libusb_config_descriptor *descConfig = nullptr; 249cc290419Sopenharmony_ci int ret = libusb_get_active_config_descriptor(device, &descConfig); 250cc290419Sopenharmony_ci if (ret != 0) { 251cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "get active config des fail, errno is %d.", errno); 252cc290419Sopenharmony_ci return false; 253cc290419Sopenharmony_ci } 254cc290419Sopenharmony_ci bool hasValid = false; 255cc290419Sopenharmony_ci for (unsigned int j = 0; j < descConfig->bNumInterfaces; ++j) { 256cc290419Sopenharmony_ci const struct libusb_interface *interface = &descConfig->interface[j]; 257cc290419Sopenharmony_ci if (interface->num_altsetting < 1) { 258cc290419Sopenharmony_ci continue; 259cc290419Sopenharmony_ci } 260cc290419Sopenharmony_ci const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; 261cc290419Sopenharmony_ci if (!IsDebuggableDev(ifDescriptor)) { 262cc290419Sopenharmony_ci continue; 263cc290419Sopenharmony_ci } 264cc290419Sopenharmony_ci hasValid = true; 265cc290419Sopenharmony_ci break; 266cc290419Sopenharmony_ci } 267cc290419Sopenharmony_ci return hasValid; 268cc290419Sopenharmony_ci} 269cc290419Sopenharmony_ci 270cc290419Sopenharmony_ci// Main thread USB operates in this thread 271cc290419Sopenharmony_civoid HdcHostUSB::UsbWorkThread(void *arg) 272cc290419Sopenharmony_ci{ 273cc290419Sopenharmony_ci HdcHostUSB *thisClass = (HdcHostUSB *)arg; 274cc290419Sopenharmony_ci constexpr uint8_t usbHandleTimeout = 30; // second 275cc290419Sopenharmony_ci while (thisClass->modRunning) { 276cc290419Sopenharmony_ci struct timeval zerotime; 277cc290419Sopenharmony_ci zerotime.tv_sec = usbHandleTimeout; 278cc290419Sopenharmony_ci zerotime.tv_usec = 0; // if == 0,windows will be high CPU load 279cc290419Sopenharmony_ci libusb_handle_events_timeout(thisClass->ctxUSB, &zerotime); 280cc290419Sopenharmony_ci } 281cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Host Sessionbase usb workthread finish"); 282cc290419Sopenharmony_ci} 283cc290419Sopenharmony_ci 284cc290419Sopenharmony_ciint HdcHostUSB::StartupUSBWork() 285cc290419Sopenharmony_ci{ 286cc290419Sopenharmony_ci // Because libusb(winusb backend) does not support hotplug under win32, we use list mode for all platforms 287cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "USBHost loopfind mode"); 288cc290419Sopenharmony_ci devListWatcher.data = this; 289cc290419Sopenharmony_ci uv_timer_start(&devListWatcher, WatchUsbNodeChange, 0, DEVICE_CHECK_INTERVAL); 290cc290419Sopenharmony_ci // Running pendding in independent threads does not significantly improve the efficiency 291cc290419Sopenharmony_ci uv_thread_create(&threadUsbWork, UsbWorkThread, this); 292cc290419Sopenharmony_ci return 0; 293cc290419Sopenharmony_ci} 294cc290419Sopenharmony_ci 295cc290419Sopenharmony_ciint HdcHostUSB::CheckDescriptor(HUSB hUSB, libusb_device_descriptor& desc) 296cc290419Sopenharmony_ci{ 297cc290419Sopenharmony_ci char serialNum[BUF_SIZE_MEDIUM] = ""; 298cc290419Sopenharmony_ci int childRet = 0; 299cc290419Sopenharmony_ci uint8_t curBus = libusb_get_bus_number(hUSB->device); 300cc290419Sopenharmony_ci uint8_t curDev = libusb_get_device_address(hUSB->device); 301cc290419Sopenharmony_ci hUSB->busId = curBus; 302cc290419Sopenharmony_ci hUSB->devId = curDev; 303cc290419Sopenharmony_ci if (libusb_get_device_descriptor(hUSB->device, &desc)) { 304cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "CheckDescriptor libusb_get_device_descriptor failed %d-%d", curBus, curDev); 305cc290419Sopenharmony_ci return -1; 306cc290419Sopenharmony_ci } 307cc290419Sopenharmony_ci // Get the serial number of the device, if there is no serial number, use the ID number to replace 308cc290419Sopenharmony_ci // If the device is not in time, occasionally can't get it, this is determined by the external factor, cannot be 309cc290419Sopenharmony_ci // changed. LIBUSB_SUCCESS 310cc290419Sopenharmony_ci childRet = libusb_get_string_descriptor_ascii(hUSB->devHandle, desc.iSerialNumber, (uint8_t *)serialNum, 311cc290419Sopenharmony_ci sizeof(serialNum)); 312cc290419Sopenharmony_ci if (childRet < 0) { 313cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "CheckDescriptor libusb_get_string_descriptor_ascii failed %d-%d", curBus, curDev); 314cc290419Sopenharmony_ci return -1; 315cc290419Sopenharmony_ci } else { 316cc290419Sopenharmony_ci hUSB->serialNumber = serialNum; 317cc290419Sopenharmony_ci } 318cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "CheckDescriptor busId-devId:%d-%d serialNum:%s", curBus, curDev, 319cc290419Sopenharmony_ci Hdc::MaskString(serialNum).c_str()); 320cc290419Sopenharmony_ci return 0; 321cc290419Sopenharmony_ci} 322cc290419Sopenharmony_ci 323cc290419Sopenharmony_ci// hSession can be null 324cc290419Sopenharmony_civoid HdcHostUSB::UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus) 325cc290419Sopenharmony_ci{ 326cc290419Sopenharmony_ci // add to list 327cc290419Sopenharmony_ci HdcServer *pServer = (HdcServer *)clsMainBase; 328cc290419Sopenharmony_ci HdcDaemonInformation di; 329cc290419Sopenharmony_ci di.connectKey = hUSB->serialNumber; 330cc290419Sopenharmony_ci di.connType = CONN_USB; 331cc290419Sopenharmony_ci di.connStatus = connStatus; 332cc290419Sopenharmony_ci di.hSession = hSession; 333cc290419Sopenharmony_ci di.usbMountPoint = ""; 334cc290419Sopenharmony_ci di.usbMountPoint = Base::StringFormat("%d-%d", hUSB->busId, hUSB->devId); 335cc290419Sopenharmony_ci 336cc290419Sopenharmony_ci HDaemonInfo pDi = nullptr; 337cc290419Sopenharmony_ci HDaemonInfo hdiNew = &di; 338cc290419Sopenharmony_ci pServer->AdminDaemonMap(OP_QUERY, hUSB->serialNumber, pDi); 339cc290419Sopenharmony_ci if (!pDi) { 340cc290419Sopenharmony_ci pServer->AdminDaemonMap(OP_ADD, hUSB->serialNumber, hdiNew); 341cc290419Sopenharmony_ci } else { 342cc290419Sopenharmony_ci pServer->AdminDaemonMap(OP_UPDATE, hUSB->serialNumber, hdiNew); 343cc290419Sopenharmony_ci } 344cc290419Sopenharmony_ci} 345cc290419Sopenharmony_ci 346cc290419Sopenharmony_cibool HdcHostUSB::IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor) 347cc290419Sopenharmony_ci{ 348cc290419Sopenharmony_ci constexpr uint8_t harmonyEpNum = 2; 349cc290419Sopenharmony_ci constexpr uint8_t harmonyClass = 0xff; 350cc290419Sopenharmony_ci constexpr uint8_t harmonySubClass = 0x50; 351cc290419Sopenharmony_ci constexpr uint8_t harmonyProtocol = 0x01; 352cc290419Sopenharmony_ci 353cc290419Sopenharmony_ci if (ifDescriptor->bInterfaceClass != harmonyClass || ifDescriptor->bInterfaceSubClass != harmonySubClass || 354cc290419Sopenharmony_ci ifDescriptor->bInterfaceProtocol != harmonyProtocol) { 355cc290419Sopenharmony_ci return false; 356cc290419Sopenharmony_ci } 357cc290419Sopenharmony_ci if (ifDescriptor->bNumEndpoints != harmonyEpNum) { 358cc290419Sopenharmony_ci return false; 359cc290419Sopenharmony_ci } 360cc290419Sopenharmony_ci return true; 361cc290419Sopenharmony_ci} 362cc290419Sopenharmony_ci 363cc290419Sopenharmony_ciint HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB, libusb_device_descriptor& desc) 364cc290419Sopenharmony_ci{ 365cc290419Sopenharmony_ci struct libusb_config_descriptor *descConfig = nullptr; 366cc290419Sopenharmony_ci int ret = libusb_get_active_config_descriptor(device, &descConfig); 367cc290419Sopenharmony_ci if (ret != 0) { 368cc290419Sopenharmony_ci#ifdef HOST_MAC 369cc290419Sopenharmony_ci if ((desc.bDeviceClass == 0xFF) 370cc290419Sopenharmony_ci && (desc.bDeviceSubClass == 0xFF) 371cc290419Sopenharmony_ci && (desc.bDeviceProtocol == 0xFF)) { 372cc290419Sopenharmony_ci ret = libusb_set_configuration(hUSB->devHandle, 1); 373cc290419Sopenharmony_ci if (ret != 0) { 374cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "set config failed ret:%d", ret); 375cc290419Sopenharmony_ci return -1; 376cc290419Sopenharmony_ci } 377cc290419Sopenharmony_ci } 378cc290419Sopenharmony_ci 379cc290419Sopenharmony_ci ret = libusb_get_active_config_descriptor(device, &descConfig); 380cc290419Sopenharmony_ci if (ret != 0) { 381cc290419Sopenharmony_ci#endif 382cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "get active config descriptor failed ret:%d", ret); 383cc290419Sopenharmony_ci return -1; 384cc290419Sopenharmony_ci } 385cc290419Sopenharmony_ci#ifdef HOST_MAC 386cc290419Sopenharmony_ci } 387cc290419Sopenharmony_ci#endif 388cc290419Sopenharmony_ci 389cc290419Sopenharmony_ci ret = -1; 390cc290419Sopenharmony_ci CheckUsbEndpoint(ret, hUSB, descConfig); 391cc290419Sopenharmony_ci libusb_free_config_descriptor(descConfig); 392cc290419Sopenharmony_ci return ret; 393cc290419Sopenharmony_ci} 394cc290419Sopenharmony_ci 395cc290419Sopenharmony_civoid HdcHostUSB::CheckUsbEndpoint(int& ret, HUSB hUSB, libusb_config_descriptor *descConfig) 396cc290419Sopenharmony_ci{ 397cc290419Sopenharmony_ci unsigned int j = 0; 398cc290419Sopenharmony_ci for (j = 0; j < descConfig->bNumInterfaces; ++j) { 399cc290419Sopenharmony_ci const struct libusb_interface *interface = &descConfig->interface[j]; 400cc290419Sopenharmony_ci if (interface->num_altsetting < 1) { 401cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "interface->num_altsetting = 0, j = %d", j); 402cc290419Sopenharmony_ci continue; 403cc290419Sopenharmony_ci } 404cc290419Sopenharmony_ci const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; 405cc290419Sopenharmony_ci if (!IsDebuggableDev(ifDescriptor)) { 406cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "IsDebuggableDev fail, j = %d", j); 407cc290419Sopenharmony_ci continue; 408cc290419Sopenharmony_ci } 409cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "CheckActiveConfig IsDebuggableDev passed and then check endpoint attr"); 410cc290419Sopenharmony_ci hUSB->interfaceNumber = ifDescriptor->bInterfaceNumber; 411cc290419Sopenharmony_ci unsigned int k = 0; 412cc290419Sopenharmony_ci for (k = 0; k < ifDescriptor->bNumEndpoints; ++k) { 413cc290419Sopenharmony_ci const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k]; 414cc290419Sopenharmony_ci if ((ep_desc->bmAttributes & 0x03) != LIBUSB_TRANSFER_TYPE_BULK) { 415cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "check ep_desc->bmAttributes fail, all %d k = %d, bmAttributes %d", 416cc290419Sopenharmony_ci ifDescriptor->bNumEndpoints, k, ep_desc->bmAttributes); 417cc290419Sopenharmony_ci continue; 418cc290419Sopenharmony_ci } 419cc290419Sopenharmony_ci if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) { 420cc290419Sopenharmony_ci hUSB->hostBulkIn.endpoint = ep_desc->bEndpointAddress; 421cc290419Sopenharmony_ci hUSB->hostBulkIn.bulkInOut = true; 422cc290419Sopenharmony_ci } else { 423cc290419Sopenharmony_ci hUSB->hostBulkOut.endpoint = ep_desc->bEndpointAddress; 424cc290419Sopenharmony_ci hUSB->wMaxPacketSizeSend = ep_desc->wMaxPacketSize; 425cc290419Sopenharmony_ci hUSB->hostBulkOut.bulkInOut = false; 426cc290419Sopenharmony_ci } 427cc290419Sopenharmony_ci } 428cc290419Sopenharmony_ci if (hUSB->hostBulkIn.endpoint == 0 || hUSB->hostBulkOut.endpoint == 0) { 429cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "hostBulkIn.endpoint %d hUSB->hostBulkOut.endpoint %d", 430cc290419Sopenharmony_ci hUSB->hostBulkIn.endpoint, hUSB->hostBulkOut.endpoint); 431cc290419Sopenharmony_ci break; 432cc290419Sopenharmony_ci } 433cc290419Sopenharmony_ci ret = 0; 434cc290419Sopenharmony_ci } 435cc290419Sopenharmony_ci} 436cc290419Sopenharmony_ci 437cc290419Sopenharmony_ci// multi-thread calll 438cc290419Sopenharmony_civoid HdcHostUSB::CancelUsbIo(HSession hSession) 439cc290419Sopenharmony_ci{ 440cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "HostUSB CancelUsbIo, sid:%u ref:%u", hSession->sessionId, uint32_t(hSession->ref)); 441cc290419Sopenharmony_ci HUSB hUSB = hSession->hUSB; 442cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(hUSB->lockDeviceHandle); 443cc290419Sopenharmony_ci if (!hUSB->hostBulkIn.isShutdown) { 444cc290419Sopenharmony_ci if (!hUSB->hostBulkIn.isComplete) { 445cc290419Sopenharmony_ci libusb_cancel_transfer(hUSB->hostBulkIn.transfer); 446cc290419Sopenharmony_ci hUSB->hostBulkIn.cv.notify_one(); 447cc290419Sopenharmony_ci } else { 448cc290419Sopenharmony_ci hUSB->hostBulkIn.isShutdown = true; 449cc290419Sopenharmony_ci } 450cc290419Sopenharmony_ci } 451cc290419Sopenharmony_ci if (!hUSB->hostBulkOut.isShutdown) { 452cc290419Sopenharmony_ci if (!hUSB->hostBulkOut.isComplete) { 453cc290419Sopenharmony_ci libusb_cancel_transfer(hUSB->hostBulkOut.transfer); 454cc290419Sopenharmony_ci hUSB->hostBulkOut.cv.notify_one(); 455cc290419Sopenharmony_ci } else { 456cc290419Sopenharmony_ci hUSB->hostBulkOut.isShutdown = true; 457cc290419Sopenharmony_ci } 458cc290419Sopenharmony_ci } 459cc290419Sopenharmony_ci} 460cc290419Sopenharmony_ci 461cc290419Sopenharmony_ci// 3rd write child-hdc-workthread 462cc290419Sopenharmony_ci// no use uvwrite, raw write to socketpair's fd 463cc290419Sopenharmony_ciint HdcHostUSB::UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int dataSize) 464cc290419Sopenharmony_ci{ 465cc290419Sopenharmony_ci HSession hSession = (HSession)stream->data; 466cc290419Sopenharmony_ci unsigned int fd = hSession->dataFd[STREAM_MAIN]; 467cc290419Sopenharmony_ci int index = 0; 468cc290419Sopenharmony_ci int childRet = 0; 469cc290419Sopenharmony_ci int retryTimes = 0; 470cc290419Sopenharmony_ci const int maxRetryTimes = 3; 471cc290419Sopenharmony_ci const int oneSecond = 1; 472cc290419Sopenharmony_ci 473cc290419Sopenharmony_ci while (index < dataSize) { 474cc290419Sopenharmony_ci fd_set fdSet; 475cc290419Sopenharmony_ci FD_ZERO(&fdSet); 476cc290419Sopenharmony_ci FD_SET(fd, &fdSet); 477cc290419Sopenharmony_ci struct timeval timeout = { 3, 0 }; 478cc290419Sopenharmony_ci childRet = select(fd + 1, nullptr, &fdSet, nullptr, &timeout); 479cc290419Sopenharmony_ci if (childRet <= 0) { 480cc290419Sopenharmony_ci hdc_strerrno(buf); 481cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "select error:%d [%s][%d] retry times %d alread send %d bytes, total %d bytes", 482cc290419Sopenharmony_ci errno, buf, childRet, retryTimes, index, dataSize); 483cc290419Sopenharmony_ci Base::DispUvStreamInfo(stream, "hostusb select failed"); 484cc290419Sopenharmony_ci if (retryTimes >= maxRetryTimes) { 485cc290419Sopenharmony_ci break; 486cc290419Sopenharmony_ci } 487cc290419Sopenharmony_ci retryTimes++; 488cc290419Sopenharmony_ci sleep(oneSecond); 489cc290419Sopenharmony_ci continue; 490cc290419Sopenharmony_ci } 491cc290419Sopenharmony_ci childRet = send(fd, reinterpret_cast<const char *>(appendData) + index, dataSize - index, 0); 492cc290419Sopenharmony_ci if (childRet < 0) { 493cc290419Sopenharmony_ci hdc_strerrno(buf); 494cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "UsbToHdcProtocol senddata err:%d [%s]", errno, buf); 495cc290419Sopenharmony_ci Base::DispUvStreamInfo(stream, "hostusb send failed"); 496cc290419Sopenharmony_ci break; 497cc290419Sopenharmony_ci } 498cc290419Sopenharmony_ci index += childRet; 499cc290419Sopenharmony_ci } 500cc290419Sopenharmony_ci hSession->stat.dataSendBytes += index; 501cc290419Sopenharmony_ci if (index != dataSize) { 502cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "UsbToHdcProtocol partialsenddata err:%d [%d]", index, dataSize); 503cc290419Sopenharmony_ci return ERR_IO_FAIL; 504cc290419Sopenharmony_ci } 505cc290419Sopenharmony_ci return index; 506cc290419Sopenharmony_ci} 507cc290419Sopenharmony_ci 508cc290419Sopenharmony_civoid LIBUSB_CALL HdcHostUSB::USBBulkCallback(struct libusb_transfer *transfer) 509cc290419Sopenharmony_ci{ 510cc290419Sopenharmony_ci auto *ep = reinterpret_cast<HostUSBEndpoint *>(transfer->user_data); 511cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(ep->mutexIo); 512cc290419Sopenharmony_ci bool retrySumit = false; 513cc290419Sopenharmony_ci int childRet = 0; 514cc290419Sopenharmony_ci do { 515cc290419Sopenharmony_ci if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { 516cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "USBBulkCallback1 failed, ret:%d", transfer->status); 517cc290419Sopenharmony_ci break; 518cc290419Sopenharmony_ci } 519cc290419Sopenharmony_ci if (!ep->bulkInOut && transfer->actual_length != transfer->length) { 520cc290419Sopenharmony_ci transfer->length -= transfer->actual_length; 521cc290419Sopenharmony_ci transfer->buffer += transfer->actual_length; 522cc290419Sopenharmony_ci retrySumit = true; 523cc290419Sopenharmony_ci break; 524cc290419Sopenharmony_ci } 525cc290419Sopenharmony_ci } while (false); 526cc290419Sopenharmony_ci while (retrySumit) { 527cc290419Sopenharmony_ci childRet = libusb_submit_transfer(transfer); 528cc290419Sopenharmony_ci if (childRet != 0) { 529cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "USBBulkCallback2 failed, ret:%d", childRet); 530cc290419Sopenharmony_ci transfer->status = LIBUSB_TRANSFER_ERROR; 531cc290419Sopenharmony_ci break; 532cc290419Sopenharmony_ci } 533cc290419Sopenharmony_ci return; 534cc290419Sopenharmony_ci } 535cc290419Sopenharmony_ci ep->isComplete = true; 536cc290419Sopenharmony_ci ep->cv.notify_one(); 537cc290419Sopenharmony_ci} 538cc290419Sopenharmony_ci 539cc290419Sopenharmony_ciint HdcHostUSB::SubmitUsbBio(HSession hSession, bool sendOrRecv, uint8_t *buf, int bufSize) 540cc290419Sopenharmony_ci{ 541cc290419Sopenharmony_ci HUSB hUSB = hSession->hUSB; 542cc290419Sopenharmony_ci int timeout = 0; 543cc290419Sopenharmony_ci int childRet = 0; 544cc290419Sopenharmony_ci int ret = ERR_IO_FAIL; 545cc290419Sopenharmony_ci HostUSBEndpoint *ep = nullptr; 546cc290419Sopenharmony_ci 547cc290419Sopenharmony_ci if (sendOrRecv) { 548cc290419Sopenharmony_ci timeout = GLOBAL_TIMEOUT * TIME_BASE; 549cc290419Sopenharmony_ci ep = &hUSB->hostBulkOut; 550cc290419Sopenharmony_ci } else { 551cc290419Sopenharmony_ci timeout = 0; // infinity 552cc290419Sopenharmony_ci ep = &hUSB->hostBulkIn; 553cc290419Sopenharmony_ci } 554cc290419Sopenharmony_ci hUSB->lockDeviceHandle.lock(); 555cc290419Sopenharmony_ci ep->isComplete = false; 556cc290419Sopenharmony_ci do { 557cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(ep->mutexIo); 558cc290419Sopenharmony_ci libusb_fill_bulk_transfer(ep->transfer, hUSB->devHandle, ep->endpoint, buf, bufSize, USBBulkCallback, ep, 559cc290419Sopenharmony_ci timeout); 560cc290419Sopenharmony_ci childRet = libusb_submit_transfer(ep->transfer); 561cc290419Sopenharmony_ci hUSB->lockDeviceHandle.unlock(); 562cc290419Sopenharmony_ci if (childRet < 0) { 563cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SubmitUsbBio libusb_submit_transfer failed, sid:%u ret:%d", 564cc290419Sopenharmony_ci hSession->sessionId, childRet); 565cc290419Sopenharmony_ci break; 566cc290419Sopenharmony_ci } 567cc290419Sopenharmony_ci ep->cv.wait(lock, [ep]() { return ep->isComplete; }); 568cc290419Sopenharmony_ci if (ep->transfer->status != 0) { 569cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SubmitUsbBio transfer failed, sid:%u status:%d", 570cc290419Sopenharmony_ci hSession->sessionId, ep->transfer->status); 571cc290419Sopenharmony_ci break; 572cc290419Sopenharmony_ci } 573cc290419Sopenharmony_ci ret = ep->transfer->actual_length; 574cc290419Sopenharmony_ci } while (false); 575cc290419Sopenharmony_ci return ret; 576cc290419Sopenharmony_ci} 577cc290419Sopenharmony_ci 578cc290419Sopenharmony_civoid HdcHostUSB::BeginUsbRead(HSession hSession) 579cc290419Sopenharmony_ci{ 580cc290419Sopenharmony_ci HUSB hUSB = hSession->hUSB; 581cc290419Sopenharmony_ci hUSB->hostBulkIn.isShutdown = false; 582cc290419Sopenharmony_ci hUSB->hostBulkOut.isShutdown = false; 583cc290419Sopenharmony_ci ++hSession->ref; 584cc290419Sopenharmony_ci // loop read 585cc290419Sopenharmony_ci std::thread([this, hSession, hUSB]() { 586cc290419Sopenharmony_ci int childRet = 0; 587cc290419Sopenharmony_ci int nextReadSize = 0; 588cc290419Sopenharmony_ci int bulkInSize = hUSB->hostBulkIn.sizeEpBuf; 589cc290419Sopenharmony_ci while (!hSession->isDead) { 590cc290419Sopenharmony_ci // if readIO < wMaxPacketSizeSend, libusb report overflow 591cc290419Sopenharmony_ci nextReadSize = (childRet < hUSB->wMaxPacketSizeSend ? 592cc290419Sopenharmony_ci hUSB->wMaxPacketSizeSend : std::min(childRet, bulkInSize)); 593cc290419Sopenharmony_ci childRet = SubmitUsbBio(hSession, false, hUSB->hostBulkIn.buf, nextReadSize); 594cc290419Sopenharmony_ci if (childRet < 0) { 595cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Read usb failed, sid:%u ret:%d", hSession->sessionId, childRet); 596cc290419Sopenharmony_ci break; 597cc290419Sopenharmony_ci } 598cc290419Sopenharmony_ci 599cc290419Sopenharmony_ci // when a session is set up for a period of time, the read data is discarded to empty the USB channel. 600cc290419Sopenharmony_ci if (hSession->isNeedDropData) { 601cc290419Sopenharmony_ci hSession->dropBytes += childRet; 602cc290419Sopenharmony_ci childRet = 0; 603cc290419Sopenharmony_ci continue; 604cc290419Sopenharmony_ci } 605cc290419Sopenharmony_ci if (childRet == 0) { 606cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Read usb return 0, continue read, sid:%u", hSession->sessionId); 607cc290419Sopenharmony_ci childRet = nextReadSize; 608cc290419Sopenharmony_ci continue; 609cc290419Sopenharmony_ci } 610cc290419Sopenharmony_ci childRet = SendToHdcStream(hSession, reinterpret_cast<uv_stream_t *>(&hSession->dataPipe[STREAM_MAIN]), 611cc290419Sopenharmony_ci hUSB->hostBulkIn.buf, childRet); 612cc290419Sopenharmony_ci if (childRet < 0) { 613cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SendToHdcStream failed, sid:%u ret:%d", hSession->sessionId, childRet); 614cc290419Sopenharmony_ci break; 615cc290419Sopenharmony_ci } 616cc290419Sopenharmony_ci } 617cc290419Sopenharmony_ci --hSession->ref; 618cc290419Sopenharmony_ci auto server = reinterpret_cast<HdcServer *>(clsMainBase); 619cc290419Sopenharmony_ci hUSB->hostBulkIn.isShutdown = true; 620cc290419Sopenharmony_ci server->FreeSession(hSession->sessionId); 621cc290419Sopenharmony_ci RemoveIgnoreDevice(hUSB->usbMountPoint); 622cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "Usb loop read finish sid:%u", hSession->sessionId); 623cc290419Sopenharmony_ci }).detach(); 624cc290419Sopenharmony_ci} 625cc290419Sopenharmony_ci 626cc290419Sopenharmony_ci// ==0 Represents new equipment and is what we need,<0 my need 627cc290419Sopenharmony_ciint HdcHostUSB::OpenDeviceMyNeed(HUSB hUSB) 628cc290419Sopenharmony_ci{ 629cc290419Sopenharmony_ci libusb_device *device = hUSB->device; 630cc290419Sopenharmony_ci int ret = -1; 631cc290419Sopenharmony_ci int OpenRet = libusb_open(device, &hUSB->devHandle); 632cc290419Sopenharmony_ci if (OpenRet != LIBUSB_SUCCESS) { 633cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "libusb_open fail xret %d", OpenRet); 634cc290419Sopenharmony_ci return ERR_LIBUSB_OPEN; 635cc290419Sopenharmony_ci } 636cc290419Sopenharmony_ci while (modRunning) { 637cc290419Sopenharmony_ci libusb_device_handle *handle = hUSB->devHandle; 638cc290419Sopenharmony_ci struct libusb_device_descriptor desc; 639cc290419Sopenharmony_ci if (CheckDescriptor(hUSB, desc)) { 640cc290419Sopenharmony_ci break; 641cc290419Sopenharmony_ci } 642cc290419Sopenharmony_ci if (CheckActiveConfig(device, hUSB, desc)) { 643cc290419Sopenharmony_ci break; 644cc290419Sopenharmony_ci } 645cc290419Sopenharmony_ci // USB filter rules are set according to specific device pedding device 646cc290419Sopenharmony_ci ret = libusb_claim_interface(handle, hUSB->interfaceNumber); 647cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "libusb_claim_interface ret %d, interfaceNumber %d", 648cc290419Sopenharmony_ci ret, hUSB->interfaceNumber); 649cc290419Sopenharmony_ci break; 650cc290419Sopenharmony_ci } 651cc290419Sopenharmony_ci if (ret) { 652cc290419Sopenharmony_ci // not my need device, release the device 653cc290419Sopenharmony_ci libusb_close(hUSB->devHandle); 654cc290419Sopenharmony_ci hUSB->devHandle = nullptr; 655cc290419Sopenharmony_ci } 656cc290419Sopenharmony_ci return ret; 657cc290419Sopenharmony_ci} 658cc290419Sopenharmony_ci 659cc290419Sopenharmony_ciint HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) 660cc290419Sopenharmony_ci{ 661cc290419Sopenharmony_ci int ret = ERR_GENERIC; 662cc290419Sopenharmony_ci HdcSessionBase *server = reinterpret_cast<HdcSessionBase *>(hSession->classInstance); 663cc290419Sopenharmony_ci ++hSession->ref; 664cc290419Sopenharmony_ci ret = SubmitUsbBio(hSession, true, data, length); 665cc290419Sopenharmony_ci if (ret < 0) { 666cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Send usb failed, sid:%u ret:%d", hSession->sessionId, ret); 667cc290419Sopenharmony_ci CancelUsbIo(hSession); 668cc290419Sopenharmony_ci hSession->hUSB->hostBulkOut.isShutdown = true; 669cc290419Sopenharmony_ci server->FreeSession(hSession->sessionId); 670cc290419Sopenharmony_ci } 671cc290419Sopenharmony_ci --hSession->ref; 672cc290419Sopenharmony_ci return ret; 673cc290419Sopenharmony_ci} 674cc290419Sopenharmony_ci 675cc290419Sopenharmony_cibool HdcHostUSB::FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB) 676cc290419Sopenharmony_ci{ 677cc290419Sopenharmony_ci libusb_device **listDevices = nullptr; 678cc290419Sopenharmony_ci bool ret = false; 679cc290419Sopenharmony_ci char tmpStr[BUF_SIZE_TINY] = ""; 680cc290419Sopenharmony_ci int busNum = 0; 681cc290419Sopenharmony_ci int devNum = 0; 682cc290419Sopenharmony_ci int curBus = 0; 683cc290419Sopenharmony_ci int curDev = 0; 684cc290419Sopenharmony_ci 685cc290419Sopenharmony_ci int device_num = libusb_get_device_list(ctxUSB, &listDevices); 686cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "device_num:%d", device_num); 687cc290419Sopenharmony_ci if (device_num <= 0) { 688cc290419Sopenharmony_ci libusb_free_device_list(listDevices, 1); 689cc290419Sopenharmony_ci return false; 690cc290419Sopenharmony_ci } 691cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "usbMountPoint:%s", usbMountPoint); 692cc290419Sopenharmony_ci if (strchr(usbMountPoint, '-') && EOK == strcpy_s(tmpStr, sizeof(tmpStr), usbMountPoint)) { 693cc290419Sopenharmony_ci *strchr(tmpStr, '-') = '\0'; 694cc290419Sopenharmony_ci busNum = atoi(tmpStr); 695cc290419Sopenharmony_ci devNum = atoi(tmpStr + strlen(tmpStr) + 1); 696cc290419Sopenharmony_ci } else { 697cc290419Sopenharmony_ci return false; 698cc290419Sopenharmony_ci } 699cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "busNum:%d devNum:%d", busNum, devNum); 700cc290419Sopenharmony_ci 701cc290419Sopenharmony_ci int i = 0; 702cc290419Sopenharmony_ci for (i = 0; i < device_num; ++i) { 703cc290419Sopenharmony_ci struct libusb_device_descriptor desc; 704cc290419Sopenharmony_ci if (LIBUSB_SUCCESS != libusb_get_device_descriptor(listDevices[i], &desc)) { 705cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "libusb_get_device_descriptor failed i:%d", i); 706cc290419Sopenharmony_ci continue; 707cc290419Sopenharmony_ci } 708cc290419Sopenharmony_ci curBus = libusb_get_bus_number(listDevices[i]); 709cc290419Sopenharmony_ci curDev = libusb_get_device_address(listDevices[i]); 710cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "curBus:%d curDev:%d", curBus, curDev); 711cc290419Sopenharmony_ci if ((curBus == busNum && curDev == devNum)) { 712cc290419Sopenharmony_ci hUSB->device = listDevices[i]; 713cc290419Sopenharmony_ci int childRet = OpenDeviceMyNeed(hUSB); 714cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "OpenDeviceMyNeed childRet:%d", childRet); 715cc290419Sopenharmony_ci if (!childRet) { 716cc290419Sopenharmony_ci ret = true; 717cc290419Sopenharmony_ci } else { 718cc290419Sopenharmony_ci string key = string(usbMountPoint); 719cc290419Sopenharmony_ci RemoveIgnoreDevice(key); 720cc290419Sopenharmony_ci } 721cc290419Sopenharmony_ci break; 722cc290419Sopenharmony_ci } 723cc290419Sopenharmony_ci } 724cc290419Sopenharmony_ci libusb_free_device_list(listDevices, 1); 725cc290419Sopenharmony_ci return ret; 726cc290419Sopenharmony_ci} 727cc290419Sopenharmony_ci 728cc290419Sopenharmony_cibool HdcHostUSB::ReadyForWorkThread(HSession hSession) 729cc290419Sopenharmony_ci{ 730cc290419Sopenharmony_ci HdcUSBBase::ReadyForWorkThread(hSession); 731cc290419Sopenharmony_ci return true; 732cc290419Sopenharmony_ci}; 733cc290419Sopenharmony_ci 734cc290419Sopenharmony_ci// Determines that daemonInfo must have the device 735cc290419Sopenharmony_ciHSession HdcHostUSB::ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi) 736cc290419Sopenharmony_ci{ 737cc290419Sopenharmony_ci HdcServer *pServer = (HdcServer *)clsMainBase; 738cc290419Sopenharmony_ci HUSB hUSB = hSession->hUSB; 739cc290419Sopenharmony_ci hUSB->usbMountPoint = pdi->usbMountPoint; 740cc290419Sopenharmony_ci hUSB->ctxUSB = ctxUSB; 741cc290419Sopenharmony_ci if (!FindDeviceByID(hUSB, hUSB->usbMountPoint.c_str(), hUSB->ctxUSB)) { 742cc290419Sopenharmony_ci pServer->FreeSession(hSession->sessionId); 743cc290419Sopenharmony_ci RemoveIgnoreDevice(hUSB->usbMountPoint); 744cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FindDeviceByID fail"); 745cc290419Sopenharmony_ci return nullptr; 746cc290419Sopenharmony_ci } 747cc290419Sopenharmony_ci UpdateUSBDaemonInfo(hUSB, hSession, STATUS_CONNECTED); 748cc290419Sopenharmony_ci hSession->isNeedDropData = true; 749cc290419Sopenharmony_ci hSession->dropBytes = 0; 750cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "ConnectDetectDaemon set isNeedDropData true, sid:%u", hSession->sessionId); 751cc290419Sopenharmony_ci BeginUsbRead(hSession); 752cc290419Sopenharmony_ci hUSB->usbMountPoint = pdi->usbMountPoint; 753cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HSession HdcHostUSB::ConnectDaemon, sid:%u", hSession->sessionId); 754cc290419Sopenharmony_ci 755cc290419Sopenharmony_ci Base::StartWorkThread(&pServer->loopMain, pServer->SessionWorkThread, Base::FinishWorkThread, hSession); 756cc290419Sopenharmony_ci // wait for thread up 757cc290419Sopenharmony_ci while (hSession->childLoop.active_handles == 0) { 758cc290419Sopenharmony_ci uv_sleep(1); 759cc290419Sopenharmony_ci } 760cc290419Sopenharmony_ci 761cc290419Sopenharmony_ci auto funcDelayStartSessionNotify = [hSession](const uint8_t flag, string &msg, const void *p) -> void { 762cc290419Sopenharmony_ci HdcServer *pServer = (HdcServer *)hSession->classInstance; 763cc290419Sopenharmony_ci auto ctrl = pServer->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); 764cc290419Sopenharmony_ci hSession->isNeedDropData = false; 765cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "funcDelayStartSessionNotify set isNeedDropData false, sid:%u drop %llu bytes data", 766cc290419Sopenharmony_ci hSession->sessionId, uint64_t(hSession->dropBytes)); 767cc290419Sopenharmony_ci Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size()); 768cc290419Sopenharmony_ci }; 769cc290419Sopenharmony_ci 770cc290419Sopenharmony_ci // delay NEW_SESSION_DROP_USB_DATA_TIME_MS to start session 771cc290419Sopenharmony_ci SendSoftResetToDaemon(hSession, 0); 772cc290419Sopenharmony_ci Base::DelayDoSimple(&(pServer->loopMain), NEW_SESSION_DROP_USB_DATA_TIME_MS, funcDelayStartSessionNotify); 773cc290419Sopenharmony_ci return hSession; 774cc290419Sopenharmony_ci} 775cc290419Sopenharmony_ci 776cc290419Sopenharmony_civoid HdcHostUSB::SendSoftResetToDaemon(HSession hSession, uint32_t sessionIdOld) 777cc290419Sopenharmony_ci{ 778cc290419Sopenharmony_ci HUSB hUSB = hSession->hUSB; 779cc290419Sopenharmony_ci hUSB->lockSendUsbBlock.lock(); 780cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "SendSoftResetToDaemon sid:%u sidOld:%u", hSession->sessionId, sessionIdOld); 781cc290419Sopenharmony_ci auto header = BuildPacketHeader(sessionIdOld, USB_OPTION_RESET, 0); 782cc290419Sopenharmony_ci if (SendUSBRaw(hSession, header.data(), header.size()) <= 0) { 783cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SendSoftResetToDaemon send failed"); 784cc290419Sopenharmony_ci } 785cc290419Sopenharmony_ci hUSB->lockSendUsbBlock.unlock(); 786cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "SendSoftResetToDaemon sid:%u finished", hSession->sessionId); 787cc290419Sopenharmony_ci} 788cc290419Sopenharmony_ci} // namespace Hdc 789