1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2024 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 17cc290419Sopenharmony_ci#include <thread> 18cc290419Sopenharmony_ci#include "usb_util.h" 19cc290419Sopenharmony_ci 20cc290419Sopenharmony_cinamespace Hdc { 21cc290419Sopenharmony_ciconstexpr uint16_t DEVICE_CHECK_INTERVAL = 3000; // ms 22cc290419Sopenharmony_ciconstexpr uint16_t BUF_SIZE_MEDIUM = 512; 23cc290419Sopenharmony_ciconstexpr uint16_t BUF_SIZE_TINY = 64; 24cc290419Sopenharmony_ciconstexpr uint8_t GLOBAL_TIMEOUT = 30; 25cc290419Sopenharmony_ciconstexpr uint16_t TIME_BASE = 1000; 26cc290419Sopenharmony_ciconstexpr uint16_t MAX_SIZE_IOBUF = 61440; 27cc290419Sopenharmony_ci 28cc290419Sopenharmony_ciuint8_t *g_bufPtr = nullptr; 29cc290419Sopenharmony_ci 30cc290419Sopenharmony_ciconst std::string StringFormat(const char * const formater, va_list &vaArgs) 31cc290419Sopenharmony_ci{ 32cc290419Sopenharmony_ci std::vector<char> args(MAX_SIZE_IOBUF); 33cc290419Sopenharmony_ci const int retSize = vsnprintf_s(args.data(), MAX_SIZE_IOBUF, MAX_SIZE_IOBUF - 1, formater, vaArgs); 34cc290419Sopenharmony_ci if (retSize < 0) { 35cc290419Sopenharmony_ci return std::string(""); 36cc290419Sopenharmony_ci } else { 37cc290419Sopenharmony_ci return std::string(args.data(), retSize); 38cc290419Sopenharmony_ci } 39cc290419Sopenharmony_ci} 40cc290419Sopenharmony_ci 41cc290419Sopenharmony_ciconst std::string StringFormat(const char * const formater, ...) 42cc290419Sopenharmony_ci{ 43cc290419Sopenharmony_ci va_list vaArgs; 44cc290419Sopenharmony_ci va_start(vaArgs, formater); 45cc290419Sopenharmony_ci std::string ret = StringFormat(formater, vaArgs); 46cc290419Sopenharmony_ci va_end(vaArgs); 47cc290419Sopenharmony_ci return ret; 48cc290419Sopenharmony_ci} 49cc290419Sopenharmony_ci 50cc290419Sopenharmony_ciHostUsb::HostUsb() 51cc290419Sopenharmony_ci{ 52cc290419Sopenharmony_ci if (libusb_init((libusb_context **)&ctxUSB) != 0) { 53cc290419Sopenharmony_ci ctxUSB = nullptr; 54cc290419Sopenharmony_ci } 55cc290419Sopenharmony_ci running = false; 56cc290419Sopenharmony_ci} 57cc290419Sopenharmony_ci 58cc290419Sopenharmony_ciHostUsb::~HostUsb() 59cc290419Sopenharmony_ci{ 60cc290419Sopenharmony_ci if (running) { 61cc290419Sopenharmony_ci Stop(); 62cc290419Sopenharmony_ci } 63cc290419Sopenharmony_ci} 64cc290419Sopenharmony_ci 65cc290419Sopenharmony_civoid HostUsb::Stop() 66cc290419Sopenharmony_ci{ 67cc290419Sopenharmony_ci if (!ctxUSB) { 68cc290419Sopenharmony_ci return; 69cc290419Sopenharmony_ci } 70cc290419Sopenharmony_ci timer->Stop(); 71cc290419Sopenharmony_ci libusb_exit((libusb_context *)ctxUSB); 72cc290419Sopenharmony_ci running = false; 73cc290419Sopenharmony_ci 74cc290419Sopenharmony_ci if (g_bufPtr != nullptr) { 75cc290419Sopenharmony_ci delete[] g_bufPtr; 76cc290419Sopenharmony_ci g_bufPtr = nullptr; 77cc290419Sopenharmony_ci } 78cc290419Sopenharmony_ci} 79cc290419Sopenharmony_ci 80cc290419Sopenharmony_ci// Main thread USB operates in this thread 81cc290419Sopenharmony_civoid HostUsb::UsbWorkThread(void *arg) 82cc290419Sopenharmony_ci{ 83cc290419Sopenharmony_ci HostUsb *thisClass = (HostUsb *)arg; 84cc290419Sopenharmony_ci constexpr uint8_t usbHandleTimeout = 30; // second 85cc290419Sopenharmony_ci while (thisClass->running) { 86cc290419Sopenharmony_ci struct timeval zerotime; 87cc290419Sopenharmony_ci zerotime.tv_sec = usbHandleTimeout; 88cc290419Sopenharmony_ci zerotime.tv_usec = 0; // if == 0,windows will be high CPU load 89cc290419Sopenharmony_ci libusb_handle_events_timeout(thisClass->ctxUSB, &zerotime); 90cc290419Sopenharmony_ci } 91cc290419Sopenharmony_ci} 92cc290419Sopenharmony_ci 93cc290419Sopenharmony_civoid HostUsb::WatchUsbNodeChange(void *arg) 94cc290419Sopenharmony_ci{ 95cc290419Sopenharmony_ci HostUsb *thisClass = (HostUsb *)arg; 96cc290419Sopenharmony_ci libusb_device **devs = nullptr; 97cc290419Sopenharmony_ci libusb_device *dev = nullptr; 98cc290419Sopenharmony_ci ssize_t cnt = libusb_get_device_list(thisClass->ctxUSB, &devs); 99cc290419Sopenharmony_ci if (cnt < 0) { 100cc290419Sopenharmony_ci return; 101cc290419Sopenharmony_ci } 102cc290419Sopenharmony_ci int i = 0; 103cc290419Sopenharmony_ci // linux replug devid increment,windows will be not 104cc290419Sopenharmony_ci while ((dev = devs[i++]) != nullptr) { // must postfix++ 105cc290419Sopenharmony_ci std::string szTmpKey = StringFormat("%d-%d", libusb_get_bus_number(dev), libusb_get_device_address(dev)); 106cc290419Sopenharmony_ci // check is in ignore list 107cc290419Sopenharmony_ci UsbCheckStatus statusCheck = thisClass->mapIgnoreDevice[szTmpKey]; 108cc290419Sopenharmony_ci if (statusCheck == HOST_USB_IGNORE || statusCheck == HOST_USB_REGISTER) { 109cc290419Sopenharmony_ci continue; 110cc290419Sopenharmony_ci } 111cc290419Sopenharmony_ci std::string sn = szTmpKey; 112cc290419Sopenharmony_ci if (thisClass->HasValidDevice(dev) && !thisClass->DetectMyNeed(dev, sn)) { 113cc290419Sopenharmony_ci thisClass->ReviewUsbNodeLater(szTmpKey); 114cc290419Sopenharmony_ci } 115cc290419Sopenharmony_ci } 116cc290419Sopenharmony_ci libusb_free_device_list(devs, 1); 117cc290419Sopenharmony_ci} 118cc290419Sopenharmony_ci 119cc290419Sopenharmony_civoid HostUsb::ReviewUsbNodeLater(string &nodeKey) 120cc290419Sopenharmony_ci{ 121cc290419Sopenharmony_ci // add to ignore list 122cc290419Sopenharmony_ci mapIgnoreDevice[nodeKey] = HOST_USB_IGNORE; 123cc290419Sopenharmony_ci RemoveIgnoreDevice(nodeKey); 124cc290419Sopenharmony_ci} 125cc290419Sopenharmony_ci 126cc290419Sopenharmony_cibool HostUsb::HasValidDevice(libusb_device *device) 127cc290419Sopenharmony_ci{ 128cc290419Sopenharmony_ci struct libusb_config_descriptor *descConfig = nullptr; 129cc290419Sopenharmony_ci int ret = libusb_get_active_config_descriptor(device, &descConfig); 130cc290419Sopenharmony_ci if (ret != 0) { 131cc290419Sopenharmony_ci return false; 132cc290419Sopenharmony_ci } 133cc290419Sopenharmony_ci bool hasValid = false; 134cc290419Sopenharmony_ci for (unsigned int j = 0; j < descConfig->bNumInterfaces; ++j) { 135cc290419Sopenharmony_ci const struct libusb_interface *interface = &descConfig->interface[j]; 136cc290419Sopenharmony_ci if (interface->num_altsetting < 1) { 137cc290419Sopenharmony_ci continue; 138cc290419Sopenharmony_ci } 139cc290419Sopenharmony_ci const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; 140cc290419Sopenharmony_ci if (!IsDebuggableDev(ifDescriptor)) { 141cc290419Sopenharmony_ci continue; 142cc290419Sopenharmony_ci } 143cc290419Sopenharmony_ci hasValid = true; 144cc290419Sopenharmony_ci break; 145cc290419Sopenharmony_ci } 146cc290419Sopenharmony_ci return hasValid; 147cc290419Sopenharmony_ci} 148cc290419Sopenharmony_ci 149cc290419Sopenharmony_cibool HostUsb::IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor) 150cc290419Sopenharmony_ci{ 151cc290419Sopenharmony_ci constexpr uint8_t harmonyEpNum = 2; 152cc290419Sopenharmony_ci constexpr uint8_t harmonyClass = 0xff; 153cc290419Sopenharmony_ci constexpr uint8_t harmonySubClass = 0x50; 154cc290419Sopenharmony_ci constexpr uint8_t harmonyProtocol = 0x01; 155cc290419Sopenharmony_ci 156cc290419Sopenharmony_ci if (ifDescriptor->bInterfaceClass != harmonyClass || ifDescriptor->bInterfaceSubClass != harmonySubClass || 157cc290419Sopenharmony_ci ifDescriptor->bInterfaceProtocol != harmonyProtocol) { 158cc290419Sopenharmony_ci return false; 159cc290419Sopenharmony_ci } 160cc290419Sopenharmony_ci if (ifDescriptor->bNumEndpoints != harmonyEpNum) { 161cc290419Sopenharmony_ci return false; 162cc290419Sopenharmony_ci } 163cc290419Sopenharmony_ci return true; 164cc290419Sopenharmony_ci} 165cc290419Sopenharmony_ci 166cc290419Sopenharmony_cibool HostUsb::DetectMyNeed(libusb_device *device, string &sn) 167cc290419Sopenharmony_ci{ 168cc290419Sopenharmony_ci HUSB hUSB = new(std::nothrow) HdcUSB(); 169cc290419Sopenharmony_ci if (hUSB == nullptr) { 170cc290419Sopenharmony_ci return false; 171cc290419Sopenharmony_ci } 172cc290419Sopenharmony_ci hUSB->device = device; 173cc290419Sopenharmony_ci // just get usb SN, close handle immediately 174cc290419Sopenharmony_ci int childRet = OpenDeviceMyNeed(hUSB); 175cc290419Sopenharmony_ci if (childRet < 0) { 176cc290419Sopenharmony_ci delete hUSB; 177cc290419Sopenharmony_ci return false; 178cc290419Sopenharmony_ci } 179cc290419Sopenharmony_ci UpdateUSBDaemonInfo(hUSB, STATUS_READY); 180cc290419Sopenharmony_ci mapIgnoreDevice[sn] = HOST_USB_REGISTER; 181cc290419Sopenharmony_ci mapUsbDevice[hUSB->serialNumber] = hUSB; 182cc290419Sopenharmony_ci return true; 183cc290419Sopenharmony_ci} 184cc290419Sopenharmony_ci 185cc290419Sopenharmony_civoid HostUsb::UpdateUSBDaemonInfo(HUSB hUSB, uint8_t connStatus) 186cc290419Sopenharmony_ci{ 187cc290419Sopenharmony_ci // add to list 188cc290419Sopenharmony_ci HdcDaemonInformation di; 189cc290419Sopenharmony_ci di.connectKey = hUSB->serialNumber; 190cc290419Sopenharmony_ci di.connType = CONN_USB; 191cc290419Sopenharmony_ci di.connStatus = connStatus; 192cc290419Sopenharmony_ci di.usbMountPoint = ""; 193cc290419Sopenharmony_ci di.usbMountPoint = StringFormat("%d-%d", hUSB->busId, hUSB->devId); 194cc290419Sopenharmony_ci 195cc290419Sopenharmony_ci HDaemonInfo pDi = nullptr; 196cc290419Sopenharmony_ci HDaemonInfo hdiNew = &di; 197cc290419Sopenharmony_ci AdminDaemonMap(OP_QUERY, hUSB->serialNumber, pDi); 198cc290419Sopenharmony_ci if (!pDi) { 199cc290419Sopenharmony_ci AdminDaemonMap(OP_ADD, hUSB->serialNumber, hdiNew); 200cc290419Sopenharmony_ci } else { 201cc290419Sopenharmony_ci AdminDaemonMap(OP_UPDATE, hUSB->serialNumber, hdiNew); 202cc290419Sopenharmony_ci if (connStatus == STATUS_OFFLINE) { 203cc290419Sopenharmony_ci RemoveIgnoreDevice(di.usbMountPoint); 204cc290419Sopenharmony_ci } 205cc290419Sopenharmony_ci } 206cc290419Sopenharmony_ci} 207cc290419Sopenharmony_ci 208cc290419Sopenharmony_ci// ==0 Represents new equipment and is what we need,<0 my need 209cc290419Sopenharmony_ciint HostUsb::OpenDeviceMyNeed(HUSB hUSB) 210cc290419Sopenharmony_ci{ 211cc290419Sopenharmony_ci libusb_device *device = hUSB->device; 212cc290419Sopenharmony_ci int ret = -1; 213cc290419Sopenharmony_ci int openRet = libusb_open(device, &hUSB->devHandle); 214cc290419Sopenharmony_ci if (openRet != LIBUSB_SUCCESS) { 215cc290419Sopenharmony_ci return -1; 216cc290419Sopenharmony_ci } 217cc290419Sopenharmony_ci while (running) { 218cc290419Sopenharmony_ci libusb_device_handle *handle = hUSB->devHandle; 219cc290419Sopenharmony_ci struct libusb_device_descriptor desc; 220cc290419Sopenharmony_ci if (CheckDescriptor(hUSB, desc)) { 221cc290419Sopenharmony_ci break; 222cc290419Sopenharmony_ci } 223cc290419Sopenharmony_ci#ifdef HOST_MAC 224cc290419Sopenharmony_ci if (CheckActiveConfig(device, hUSB, desc)) { 225cc290419Sopenharmony_ci#else 226cc290419Sopenharmony_ci if (CheckActiveConfig(device, hUSB)) { 227cc290419Sopenharmony_ci#endif 228cc290419Sopenharmony_ci break; 229cc290419Sopenharmony_ci } 230cc290419Sopenharmony_ci 231cc290419Sopenharmony_ci // USB filter rules are set according to specific device pedding device 232cc290419Sopenharmony_ci ret = libusb_claim_interface(handle, hUSB->interfaceNumber); 233cc290419Sopenharmony_ci break; 234cc290419Sopenharmony_ci } 235cc290419Sopenharmony_ci if (ret) { 236cc290419Sopenharmony_ci // not my need device, release the device 237cc290419Sopenharmony_ci libusb_close(hUSB->devHandle); 238cc290419Sopenharmony_ci hUSB->devHandle = nullptr; 239cc290419Sopenharmony_ci } 240cc290419Sopenharmony_ci return ret; 241cc290419Sopenharmony_ci} 242cc290419Sopenharmony_ci 243cc290419Sopenharmony_ciint HostUsb::CheckDescriptor(HUSB hUSB, libusb_device_descriptor& desc) 244cc290419Sopenharmony_ci{ 245cc290419Sopenharmony_ci char serialNum[BUF_SIZE_MEDIUM] = ""; 246cc290419Sopenharmony_ci int childRet = 0; 247cc290419Sopenharmony_ci uint8_t curBus = libusb_get_bus_number(hUSB->device); 248cc290419Sopenharmony_ci uint8_t curDev = libusb_get_device_address(hUSB->device); 249cc290419Sopenharmony_ci hUSB->busId = curBus; 250cc290419Sopenharmony_ci hUSB->devId = curDev; 251cc290419Sopenharmony_ci if (libusb_get_device_descriptor(hUSB->device, &desc)) { 252cc290419Sopenharmony_ci return -1; 253cc290419Sopenharmony_ci } 254cc290419Sopenharmony_ci // Get the serial number of the device, if there is no serial number, use the ID number to replace 255cc290419Sopenharmony_ci // If the device is not in time, occasionally can't get it, this is determined by the external factor, cannot be 256cc290419Sopenharmony_ci // changed. LIBUSB_SUCCESS 257cc290419Sopenharmony_ci childRet = libusb_get_string_descriptor_ascii(hUSB->devHandle, desc.iSerialNumber, (uint8_t *)serialNum, 258cc290419Sopenharmony_ci sizeof(serialNum)); 259cc290419Sopenharmony_ci if (childRet < 0) { 260cc290419Sopenharmony_ci return -1; 261cc290419Sopenharmony_ci } else { 262cc290419Sopenharmony_ci hUSB->serialNumber = serialNum; 263cc290419Sopenharmony_ci } 264cc290419Sopenharmony_ci return 0; 265cc290419Sopenharmony_ci} 266cc290419Sopenharmony_ci 267cc290419Sopenharmony_ci#ifdef HOST_MAC 268cc290419Sopenharmony_ciint HostUsb::CheckActiveConfig(libusb_device *device, HUSB hUSB, libusb_device_descriptor& desc) 269cc290419Sopenharmony_ci#else 270cc290419Sopenharmony_ciint HostUsb::CheckActiveConfig(libusb_device *device, HUSB hUSB) 271cc290419Sopenharmony_ci#endif 272cc290419Sopenharmony_ci{ 273cc290419Sopenharmony_ci struct libusb_config_descriptor *descConfig = nullptr; 274cc290419Sopenharmony_ci int ret = libusb_get_active_config_descriptor(device, &descConfig); 275cc290419Sopenharmony_ci if (ret != 0) { 276cc290419Sopenharmony_ci#ifdef HOST_MAC 277cc290419Sopenharmony_ci if ((desc.bDeviceClass == 0xFF) 278cc290419Sopenharmony_ci && (desc.bDeviceSubClass == 0xFF) 279cc290419Sopenharmony_ci && (desc.bDeviceProtocol == 0xFF)) { 280cc290419Sopenharmony_ci ret = libusb_set_configuration(hUSB->devHandle, 1); 281cc290419Sopenharmony_ci if (ret != 0) { 282cc290419Sopenharmony_ci return -1; 283cc290419Sopenharmony_ci } 284cc290419Sopenharmony_ci } 285cc290419Sopenharmony_ci 286cc290419Sopenharmony_ci ret = libusb_get_active_config_descriptor(device, &descConfig); 287cc290419Sopenharmony_ci if (ret != 0) { 288cc290419Sopenharmony_ci#endif 289cc290419Sopenharmony_ci return -1; 290cc290419Sopenharmony_ci } 291cc290419Sopenharmony_ci#ifdef HOST_MAC 292cc290419Sopenharmony_ci } 293cc290419Sopenharmony_ci#endif 294cc290419Sopenharmony_ci 295cc290419Sopenharmony_ci ret = -1; 296cc290419Sopenharmony_ci CheckUsbEndpoint(ret, hUSB, descConfig); 297cc290419Sopenharmony_ci libusb_free_config_descriptor(descConfig); 298cc290419Sopenharmony_ci return ret; 299cc290419Sopenharmony_ci} 300cc290419Sopenharmony_ci 301cc290419Sopenharmony_civoid HostUsb::CheckUsbEndpoint(int& ret, HUSB hUSB, libusb_config_descriptor *descConfig) 302cc290419Sopenharmony_ci{ 303cc290419Sopenharmony_ci unsigned int j = 0; 304cc290419Sopenharmony_ci for (j = 0; j < descConfig->bNumInterfaces; ++j) { 305cc290419Sopenharmony_ci const struct libusb_interface *interface = &descConfig->interface[j]; 306cc290419Sopenharmony_ci if (interface->num_altsetting < 1) { 307cc290419Sopenharmony_ci continue; 308cc290419Sopenharmony_ci } 309cc290419Sopenharmony_ci const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; 310cc290419Sopenharmony_ci if (!IsDebuggableDev(ifDescriptor)) { 311cc290419Sopenharmony_ci continue; 312cc290419Sopenharmony_ci } 313cc290419Sopenharmony_ci hUSB->interfaceNumber = ifDescriptor->bInterfaceNumber; 314cc290419Sopenharmony_ci unsigned int k = 0; 315cc290419Sopenharmony_ci for (k = 0; k < ifDescriptor->bNumEndpoints; ++k) { 316cc290419Sopenharmony_ci const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k]; 317cc290419Sopenharmony_ci if ((ep_desc->bmAttributes & 0x03) != LIBUSB_TRANSFER_TYPE_BULK) { 318cc290419Sopenharmony_ci continue; 319cc290419Sopenharmony_ci } 320cc290419Sopenharmony_ci if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) { 321cc290419Sopenharmony_ci hUSB->hostBulkIn.endpoint = ep_desc->bEndpointAddress; 322cc290419Sopenharmony_ci hUSB->hostBulkIn.bulkInOut = true; 323cc290419Sopenharmony_ci } else { 324cc290419Sopenharmony_ci hUSB->hostBulkOut.endpoint = ep_desc->bEndpointAddress; 325cc290419Sopenharmony_ci hUSB->wMaxPacketSizeSend = ep_desc->wMaxPacketSize; 326cc290419Sopenharmony_ci hUSB->hostBulkOut.bulkInOut = false; 327cc290419Sopenharmony_ci } 328cc290419Sopenharmony_ci } 329cc290419Sopenharmony_ci if (hUSB->hostBulkIn.endpoint == 0 || hUSB->hostBulkOut.endpoint == 0) { 330cc290419Sopenharmony_ci break; 331cc290419Sopenharmony_ci } 332cc290419Sopenharmony_ci ret = 0; 333cc290419Sopenharmony_ci } 334cc290419Sopenharmony_ci} 335cc290419Sopenharmony_ci 336cc290419Sopenharmony_cibool HostUsb::FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB) 337cc290419Sopenharmony_ci{ 338cc290419Sopenharmony_ci libusb_device **listDevices = nullptr; 339cc290419Sopenharmony_ci bool ret = false; 340cc290419Sopenharmony_ci char tmpStr[BUF_SIZE_TINY] = ""; 341cc290419Sopenharmony_ci int busNum = 0; 342cc290419Sopenharmony_ci int devNum = 0; 343cc290419Sopenharmony_ci int curBus = 0; 344cc290419Sopenharmony_ci int curDev = 0; 345cc290419Sopenharmony_ci 346cc290419Sopenharmony_ci int deviceNum = libusb_get_device_list(ctxUSB, &listDevices); 347cc290419Sopenharmony_ci if (deviceNum <= 0) { 348cc290419Sopenharmony_ci libusb_free_device_list(listDevices, 1); 349cc290419Sopenharmony_ci return false; 350cc290419Sopenharmony_ci } 351cc290419Sopenharmony_ci if (strchr(usbMountPoint, '-') && EOK == strcpy_s(tmpStr, sizeof(tmpStr), usbMountPoint)) { 352cc290419Sopenharmony_ci *strchr(tmpStr, '-') = '\0'; 353cc290419Sopenharmony_ci busNum = atoi(tmpStr); 354cc290419Sopenharmony_ci devNum = atoi(tmpStr + strlen(tmpStr) + 1); 355cc290419Sopenharmony_ci } else { 356cc290419Sopenharmony_ci return false; 357cc290419Sopenharmony_ci } 358cc290419Sopenharmony_ci 359cc290419Sopenharmony_ci int i = 0; 360cc290419Sopenharmony_ci for (i = 0; i < deviceNum; ++i) { 361cc290419Sopenharmony_ci struct libusb_device_descriptor desc; 362cc290419Sopenharmony_ci if (LIBUSB_SUCCESS != libusb_get_device_descriptor(listDevices[i], &desc)) { 363cc290419Sopenharmony_ci continue; 364cc290419Sopenharmony_ci } 365cc290419Sopenharmony_ci curBus = libusb_get_bus_number(listDevices[i]); 366cc290419Sopenharmony_ci curDev = libusb_get_device_address(listDevices[i]); 367cc290419Sopenharmony_ci if ((curBus == busNum && curDev == devNum)) { 368cc290419Sopenharmony_ci hUSB->device = listDevices[i]; 369cc290419Sopenharmony_ci int childRet = OpenDeviceMyNeed(hUSB); 370cc290419Sopenharmony_ci if (!childRet) { 371cc290419Sopenharmony_ci ret = true; 372cc290419Sopenharmony_ci } else { 373cc290419Sopenharmony_ci string key = string(usbMountPoint); 374cc290419Sopenharmony_ci RemoveIgnoreDevice(key); 375cc290419Sopenharmony_ci } 376cc290419Sopenharmony_ci break; 377cc290419Sopenharmony_ci } 378cc290419Sopenharmony_ci } 379cc290419Sopenharmony_ci libusb_free_device_list(listDevices, 1); 380cc290419Sopenharmony_ci return ret; 381cc290419Sopenharmony_ci} 382cc290419Sopenharmony_ci 383cc290419Sopenharmony_ci// multi-thread calll 384cc290419Sopenharmony_civoid HostUsb::CancelUsbIo(HUSB hUSB) 385cc290419Sopenharmony_ci{ 386cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(hUSB->lockDeviceHandle); 387cc290419Sopenharmony_ci if (!hUSB->hostBulkIn.isShutdown) { 388cc290419Sopenharmony_ci if (!hUSB->hostBulkIn.isComplete) { 389cc290419Sopenharmony_ci libusb_cancel_transfer(hUSB->hostBulkIn.transfer); 390cc290419Sopenharmony_ci hUSB->hostBulkIn.cv.notify_one(); 391cc290419Sopenharmony_ci } else { 392cc290419Sopenharmony_ci hUSB->hostBulkIn.isShutdown = true; 393cc290419Sopenharmony_ci } 394cc290419Sopenharmony_ci } 395cc290419Sopenharmony_ci if (!hUSB->hostBulkOut.isShutdown) { 396cc290419Sopenharmony_ci if (!hUSB->hostBulkOut.isComplete) { 397cc290419Sopenharmony_ci libusb_cancel_transfer(hUSB->hostBulkOut.transfer); 398cc290419Sopenharmony_ci hUSB->hostBulkOut.cv.notify_one(); 399cc290419Sopenharmony_ci } else { 400cc290419Sopenharmony_ci hUSB->hostBulkOut.isShutdown = true; 401cc290419Sopenharmony_ci } 402cc290419Sopenharmony_ci } 403cc290419Sopenharmony_ci} 404cc290419Sopenharmony_ci 405cc290419Sopenharmony_civoid HostUsb::RemoveIgnoreDevice(string &mountInfo) 406cc290419Sopenharmony_ci{ 407cc290419Sopenharmony_ci if (mapIgnoreDevice.count(mountInfo)) { 408cc290419Sopenharmony_ci mapIgnoreDevice.erase(mountInfo); 409cc290419Sopenharmony_ci } 410cc290419Sopenharmony_ci} 411cc290419Sopenharmony_ci 412cc290419Sopenharmony_civoid LIBUSB_CALL HostUsb::USBBulkCallback(struct libusb_transfer *transfer) 413cc290419Sopenharmony_ci{ 414cc290419Sopenharmony_ci auto *ep = reinterpret_cast<HostUSBEndpoint *>(transfer->user_data); 415cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(ep->mutexIo); 416cc290419Sopenharmony_ci bool retrySumit = false; 417cc290419Sopenharmony_ci int childRet = 0; 418cc290419Sopenharmony_ci do { 419cc290419Sopenharmony_ci if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { 420cc290419Sopenharmony_ci break; 421cc290419Sopenharmony_ci } 422cc290419Sopenharmony_ci if (!ep->bulkInOut && transfer->actual_length != transfer->length) { 423cc290419Sopenharmony_ci transfer->length -= transfer->actual_length; 424cc290419Sopenharmony_ci transfer->buffer += transfer->actual_length; 425cc290419Sopenharmony_ci retrySumit = true; 426cc290419Sopenharmony_ci break; 427cc290419Sopenharmony_ci } 428cc290419Sopenharmony_ci } while (false); 429cc290419Sopenharmony_ci while (retrySumit) { 430cc290419Sopenharmony_ci childRet = libusb_submit_transfer(transfer); 431cc290419Sopenharmony_ci if (childRet != 0) { 432cc290419Sopenharmony_ci transfer->status = LIBUSB_TRANSFER_ERROR; 433cc290419Sopenharmony_ci break; 434cc290419Sopenharmony_ci } 435cc290419Sopenharmony_ci return; 436cc290419Sopenharmony_ci } 437cc290419Sopenharmony_ci ep->isComplete = true; 438cc290419Sopenharmony_ci ep->cv.notify_one(); 439cc290419Sopenharmony_ci} 440cc290419Sopenharmony_ci 441cc290419Sopenharmony_ciPersistBuffer HostUsb::ReadUsbIO(HUSB hUSB, int exceptedSize) 442cc290419Sopenharmony_ci{ 443cc290419Sopenharmony_ci int timeout = 0; 444cc290419Sopenharmony_ci int childRet = 0; 445cc290419Sopenharmony_ci int ret = 0; 446cc290419Sopenharmony_ci 447cc290419Sopenharmony_ci HostUSBEndpoint* ep = &hUSB->hostBulkIn; 448cc290419Sopenharmony_ci 449cc290419Sopenharmony_ci if (g_bufPtr == nullptr) { 450cc290419Sopenharmony_ci g_bufPtr = new uint8_t[MAX_SIZE_IOBUF]; 451cc290419Sopenharmony_ci } 452cc290419Sopenharmony_ci 453cc290419Sopenharmony_ci hUSB->lockDeviceHandle.lock(); 454cc290419Sopenharmony_ci ep->isComplete = false; 455cc290419Sopenharmony_ci do { 456cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(ep->mutexIo); 457cc290419Sopenharmony_ci libusb_fill_bulk_transfer(ep->transfer, hUSB->devHandle, ep->endpoint, g_bufPtr, exceptedSize, 458cc290419Sopenharmony_ci USBBulkCallback, ep, timeout); 459cc290419Sopenharmony_ci childRet = libusb_submit_transfer(ep->transfer); 460cc290419Sopenharmony_ci hUSB->lockDeviceHandle.unlock(); 461cc290419Sopenharmony_ci if (childRet < 0) { 462cc290419Sopenharmony_ci break; 463cc290419Sopenharmony_ci } 464cc290419Sopenharmony_ci ep->cv.wait(lock, [ep]() { return ep->isComplete; }); 465cc290419Sopenharmony_ci if (ep->transfer->status != 0) { 466cc290419Sopenharmony_ci break; 467cc290419Sopenharmony_ci } 468cc290419Sopenharmony_ci ret = ep->transfer->actual_length; 469cc290419Sopenharmony_ci } while (false); 470cc290419Sopenharmony_ci return PersistBuffer{reinterpret_cast<char *>(g_bufPtr), static_cast<uint64_t>(ret)}; 471cc290419Sopenharmony_ci} 472cc290419Sopenharmony_ci 473cc290419Sopenharmony_ciHUSB HostUsb::GetUsbDevice(std::string connectKey) 474cc290419Sopenharmony_ci{ 475cc290419Sopenharmony_ci return mapUsbDevice[connectKey]; 476cc290419Sopenharmony_ci} 477cc290419Sopenharmony_ci 478cc290419Sopenharmony_ciint HostUsb::WriteUsbIO(HUSB hUSB, SerializedBuffer buf) 479cc290419Sopenharmony_ci{ 480cc290419Sopenharmony_ci int childRet = 0; 481cc290419Sopenharmony_ci int ret = -14000; 482cc290419Sopenharmony_ci int timeout = GLOBAL_TIMEOUT * TIME_BASE; 483cc290419Sopenharmony_ci HostUSBEndpoint *ep = &hUSB->hostBulkOut; 484cc290419Sopenharmony_ci 485cc290419Sopenharmony_ci hUSB->lockDeviceHandle.lock(); 486cc290419Sopenharmony_ci ep->isComplete = false; 487cc290419Sopenharmony_ci uint8_t* ptr = reinterpret_cast<uint8_t *>(buf.ptr); 488cc290419Sopenharmony_ci size_t size = static_cast<size_t>(buf.size); 489cc290419Sopenharmony_ci do { 490cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(ep->mutexIo); 491cc290419Sopenharmony_ci libusb_fill_bulk_transfer(ep->transfer, hUSB->devHandle, ep->endpoint, ptr, size, USBBulkCallback, ep, 492cc290419Sopenharmony_ci timeout); 493cc290419Sopenharmony_ci childRet = libusb_submit_transfer(ep->transfer); 494cc290419Sopenharmony_ci hUSB->lockDeviceHandle.unlock(); 495cc290419Sopenharmony_ci if (childRet < 0) { 496cc290419Sopenharmony_ci break; 497cc290419Sopenharmony_ci } 498cc290419Sopenharmony_ci ep->cv.wait(lock, [ep]() { return ep->isComplete; }); 499cc290419Sopenharmony_ci if (ep->transfer->status != 0) { 500cc290419Sopenharmony_ci break; 501cc290419Sopenharmony_ci } 502cc290419Sopenharmony_ci ret = ep->transfer->actual_length; 503cc290419Sopenharmony_ci } while (false); 504cc290419Sopenharmony_ci return ret; 505cc290419Sopenharmony_ci} 506cc290419Sopenharmony_ci 507cc290419Sopenharmony_ciint HostUsb::Initial() 508cc290419Sopenharmony_ci{ 509cc290419Sopenharmony_ci if (!ctxUSB) { 510cc290419Sopenharmony_ci return -1; 511cc290419Sopenharmony_ci } 512cc290419Sopenharmony_ci running = true; 513cc290419Sopenharmony_ci auto WatchUsbNodeChangeFunc = [this]() { WatchUsbNodeChange(this); }; 514cc290419Sopenharmony_ci timer = std::make_unique<CTimer>(WatchUsbNodeChangeFunc); 515cc290419Sopenharmony_ci timer->Start(DEVICE_CHECK_INTERVAL); 516cc290419Sopenharmony_ci std::thread([this]() { 517cc290419Sopenharmony_ci UsbWorkThread(this); 518cc290419Sopenharmony_ci }).detach(); 519cc290419Sopenharmony_ci return 0; 520cc290419Sopenharmony_ci} 521cc290419Sopenharmony_ci 522cc290419Sopenharmony_cistatic void BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out) 523cc290419Sopenharmony_ci{ 524cc290419Sopenharmony_ci if (fullDisplay) { 525cc290419Sopenharmony_ci string sConn; 526cc290419Sopenharmony_ci string sStatus; 527cc290419Sopenharmony_ci switch (hdi->connType) { 528cc290419Sopenharmony_ci case CONN_TCP: 529cc290419Sopenharmony_ci sConn = "TCP"; 530cc290419Sopenharmony_ci break; 531cc290419Sopenharmony_ci case CONN_USB: 532cc290419Sopenharmony_ci sConn = "USB"; 533cc290419Sopenharmony_ci break; 534cc290419Sopenharmony_ci#ifdef HDC_SUPPORT_UART 535cc290419Sopenharmony_ci case CONN_SERIAL: 536cc290419Sopenharmony_ci sConn = "UART"; 537cc290419Sopenharmony_ci break; 538cc290419Sopenharmony_ci#endif 539cc290419Sopenharmony_ci case CONN_BT: 540cc290419Sopenharmony_ci sConn = "BT"; 541cc290419Sopenharmony_ci break; 542cc290419Sopenharmony_ci default: 543cc290419Sopenharmony_ci sConn = "UNKNOW"; 544cc290419Sopenharmony_ci break; 545cc290419Sopenharmony_ci } 546cc290419Sopenharmony_ci switch (hdi->connStatus) { 547cc290419Sopenharmony_ci case STATUS_READY: 548cc290419Sopenharmony_ci sStatus = "Ready"; 549cc290419Sopenharmony_ci break; 550cc290419Sopenharmony_ci case STATUS_CONNECTED: 551cc290419Sopenharmony_ci sStatus = "Connected"; 552cc290419Sopenharmony_ci break; 553cc290419Sopenharmony_ci case STATUS_OFFLINE: 554cc290419Sopenharmony_ci sStatus = "Offline"; 555cc290419Sopenharmony_ci break; 556cc290419Sopenharmony_ci default: 557cc290419Sopenharmony_ci sStatus = "UNKNOW"; 558cc290419Sopenharmony_ci break; 559cc290419Sopenharmony_ci } 560cc290419Sopenharmony_ci out = StringFormat("%s\t\t%s\t%s\t%s\n", hdi->connectKey.c_str(), sConn.c_str(), sStatus.c_str(), 561cc290419Sopenharmony_ci hdi->devName.c_str()); 562cc290419Sopenharmony_ci } else { 563cc290419Sopenharmony_ci if (hdi->connStatus == STATUS_CONNECTED) { 564cc290419Sopenharmony_ci out = StringFormat("%s\n", hdi->connectKey.c_str()); 565cc290419Sopenharmony_ci } 566cc290419Sopenharmony_ci } 567cc290419Sopenharmony_ci} 568cc290419Sopenharmony_ci 569cc290419Sopenharmony_cistring HostUsb::GetDaemonMapList(uint8_t opType) 570cc290419Sopenharmony_ci{ 571cc290419Sopenharmony_ci string ret; 572cc290419Sopenharmony_ci bool fullDisplay = false; 573cc290419Sopenharmony_ci if (opType == OP_GET_STRLIST_FULL) { 574cc290419Sopenharmony_ci fullDisplay = true; 575cc290419Sopenharmony_ci } 576cc290419Sopenharmony_ci lockMapDaemon.lock(); 577cc290419Sopenharmony_ci map<string, HDaemonInfo>::iterator iter; 578cc290419Sopenharmony_ci string echoLine; 579cc290419Sopenharmony_ci for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { 580cc290419Sopenharmony_ci HDaemonInfo di = iter->second; 581cc290419Sopenharmony_ci if (!di) { 582cc290419Sopenharmony_ci continue; 583cc290419Sopenharmony_ci } 584cc290419Sopenharmony_ci echoLine = ""; 585cc290419Sopenharmony_ci if (opType == OP_GET_READY_STRLIST) { 586cc290419Sopenharmony_ci if (di->connStatus == STATUS_READY) { 587cc290419Sopenharmony_ci echoLine = StringFormat("%s ", di->connectKey.c_str()); 588cc290419Sopenharmony_ci ret += echoLine; 589cc290419Sopenharmony_ci } 590cc290419Sopenharmony_ci continue; 591cc290419Sopenharmony_ci } 592cc290419Sopenharmony_ci BuildDaemonVisableLine(di, fullDisplay, echoLine); 593cc290419Sopenharmony_ci ret += echoLine; 594cc290419Sopenharmony_ci } 595cc290419Sopenharmony_ci lockMapDaemon.unlock(); 596cc290419Sopenharmony_ci return ret; 597cc290419Sopenharmony_ci} 598cc290419Sopenharmony_ci 599cc290419Sopenharmony_cistring HostUsb::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut) 600cc290419Sopenharmony_ci{ 601cc290419Sopenharmony_ci string sRet; 602cc290419Sopenharmony_ci switch (opType) { 603cc290419Sopenharmony_ci case OP_ADD: { 604cc290419Sopenharmony_ci HDaemonInfo pdiNew = new(std::nothrow) HdcDaemonInformation(); 605cc290419Sopenharmony_ci if (pdiNew == nullptr) { 606cc290419Sopenharmony_ci break; 607cc290419Sopenharmony_ci } 608cc290419Sopenharmony_ci *pdiNew = *hDaemonInfoInOut; 609cc290419Sopenharmony_ci lockMapDaemon.lock(); 610cc290419Sopenharmony_ci if (!mapDaemon[hDaemonInfoInOut->connectKey]) { 611cc290419Sopenharmony_ci mapDaemon[hDaemonInfoInOut->connectKey] = pdiNew; 612cc290419Sopenharmony_ci } 613cc290419Sopenharmony_ci lockMapDaemon.unlock(); 614cc290419Sopenharmony_ci break; 615cc290419Sopenharmony_ci } 616cc290419Sopenharmony_ci case OP_GET_READY_STRLIST: 617cc290419Sopenharmony_ci sRet = GetDaemonMapList(opType); 618cc290419Sopenharmony_ci break; 619cc290419Sopenharmony_ci case OP_GET_STRLIST: 620cc290419Sopenharmony_ci case OP_GET_STRLIST_FULL: { 621cc290419Sopenharmony_ci sRet = GetDaemonMapList(opType); 622cc290419Sopenharmony_ci break; 623cc290419Sopenharmony_ci } 624cc290419Sopenharmony_ci case OP_QUERY: { 625cc290419Sopenharmony_ci lockMapDaemon.lock(); 626cc290419Sopenharmony_ci if (mapDaemon.count(connectKey)) { 627cc290419Sopenharmony_ci hDaemonInfoInOut = mapDaemon[connectKey]; 628cc290419Sopenharmony_ci } 629cc290419Sopenharmony_ci lockMapDaemon.unlock(); 630cc290419Sopenharmony_ci break; 631cc290419Sopenharmony_ci } 632cc290419Sopenharmony_ci case OP_REMOVE: { 633cc290419Sopenharmony_ci lockMapDaemon.lock(); 634cc290419Sopenharmony_ci if (mapDaemon.count(connectKey)) { 635cc290419Sopenharmony_ci mapDaemon.erase(connectKey); 636cc290419Sopenharmony_ci } 637cc290419Sopenharmony_ci lockMapDaemon.unlock(); 638cc290419Sopenharmony_ci break; 639cc290419Sopenharmony_ci } 640cc290419Sopenharmony_ci case OP_GET_ANY: { 641cc290419Sopenharmony_ci lockMapDaemon.lock(); 642cc290419Sopenharmony_ci map<string, HDaemonInfo>::iterator iter; 643cc290419Sopenharmony_ci for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { 644cc290419Sopenharmony_ci HDaemonInfo di = iter->second; 645cc290419Sopenharmony_ci // usb will be auto connected 646cc290419Sopenharmony_ci if (di->connStatus == STATUS_READY || di->connStatus == STATUS_CONNECTED) { 647cc290419Sopenharmony_ci hDaemonInfoInOut = di; 648cc290419Sopenharmony_ci break; 649cc290419Sopenharmony_ci } 650cc290419Sopenharmony_ci } 651cc290419Sopenharmony_ci lockMapDaemon.unlock(); 652cc290419Sopenharmony_ci break; 653cc290419Sopenharmony_ci } 654cc290419Sopenharmony_ci case OP_WAIT_FOR_ANY: { 655cc290419Sopenharmony_ci lockMapDaemon.lock(); 656cc290419Sopenharmony_ci map<string, HDaemonInfo>::iterator iter; 657cc290419Sopenharmony_ci for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { 658cc290419Sopenharmony_ci HDaemonInfo di = iter->second; 659cc290419Sopenharmony_ci if (di->connStatus == STATUS_CONNECTED) { 660cc290419Sopenharmony_ci hDaemonInfoInOut = di; 661cc290419Sopenharmony_ci break; 662cc290419Sopenharmony_ci } 663cc290419Sopenharmony_ci } 664cc290419Sopenharmony_ci lockMapDaemon.unlock(); 665cc290419Sopenharmony_ci break; 666cc290419Sopenharmony_ci } 667cc290419Sopenharmony_ci case OP_UPDATE: { // Cannot update the Object HDi lower key value by direct value 668cc290419Sopenharmony_ci lockMapDaemon.lock(); 669cc290419Sopenharmony_ci HDaemonInfo hdi = mapDaemon[hDaemonInfoInOut->connectKey]; 670cc290419Sopenharmony_ci if (hdi) { 671cc290419Sopenharmony_ci *mapDaemon[hDaemonInfoInOut->connectKey] = *hDaemonInfoInOut; 672cc290419Sopenharmony_ci } 673cc290419Sopenharmony_ci lockMapDaemon.unlock(); 674cc290419Sopenharmony_ci break; 675cc290419Sopenharmony_ci } 676cc290419Sopenharmony_ci default: 677cc290419Sopenharmony_ci break; 678cc290419Sopenharmony_ci } 679cc290419Sopenharmony_ci return sRet; 680cc290419Sopenharmony_ci} 681cc290419Sopenharmony_ci}