• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "host_usb.h"
16 #include "server.h"
17 #include <thread>
18 namespace Hdc {
HdcHostUSB(const bool serverOrDaemonIn,void * ptrMainBase,void * ctxUSBin)19 HdcHostUSB::HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin)
20     : HdcUSBBase(serverOrDaemonIn, ptrMainBase)
21 {
22     modRunning = false;
23     HdcServer *pServer = (HdcServer *)ptrMainBase;
24     ctxUSB = (libusb_context *)ctxUSBin;
25     uv_timer_init(&pServer->loopMain, &devListWatcher);
26 }
27 
~HdcHostUSB()28 HdcHostUSB::~HdcHostUSB()
29 {
30     if (modRunning) {
31         Stop();
32     }
33     WRITE_LOG(LOG_DEBUG, "~HdcHostUSB");
34 }
35 
Stop()36 void HdcHostUSB::Stop()
37 {
38     if (!ctxUSB) {
39         return;
40     }
41     Base::TryCloseHandle((uv_handle_t *)&devListWatcher);
42     modRunning = false;
43 }
44 
Initial()45 int HdcHostUSB::Initial()
46 {
47     if (!ctxUSB) {
48         WRITE_LOG(LOG_FATAL, "USB mod ctxUSB is nullptr, recompile please");
49         return -1;
50     }
51     WRITE_LOG(LOG_DEBUG, "HdcHostUSB init");
52     modRunning = true;
53     StartupUSBWork();  // Main thread registration, IO in sub-thread
54     return 0;
55 }
56 
DetectMyNeed(libusb_device * device,string & sn)57 bool HdcHostUSB::DetectMyNeed(libusb_device *device, string &sn)
58 {
59     HUSB hUSB = new(std::nothrow) HdcUSB();
60     if (hUSB == nullptr) {
61         WRITE_LOG(LOG_FATAL, "DetectMyNeed new hUSB failed");
62         return false;
63     }
64     hUSB->device = device;
65     // just get usb SN, close handle immediately
66     int childRet = OpenDeviceMyNeed(hUSB);
67     if (childRet < 0) {
68         WRITE_LOG(LOG_WARN, "DetectMyNeed childRet:%d sn:%s", childRet, sn.c_str());
69         delete hUSB;
70         return false;
71     }
72     libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber);
73     libusb_close(hUSB->devHandle);
74     hUSB->devHandle = nullptr;
75 
76     WRITE_LOG(LOG_INFO, "Needed device found, busid:%d devid:%d connectkey:%s", hUSB->busId, hUSB->devId,
77               hUSB->serialNumber.c_str());
78     // USB device is automatically connected after recognition, auto connect USB
79     UpdateUSBDaemonInfo(hUSB, nullptr, STATUS_READY);
80     HdcServer *hdcServer = (HdcServer *)clsMainBase;
81     HSession hSession = hdcServer->MallocSession(true, CONN_USB, this);
82     hSession->connectKey = hUSB->serialNumber;
83     uv_timer_t *waitTimeDoCmd = new(std::nothrow) uv_timer_t;
84     if (waitTimeDoCmd == nullptr) {
85         WRITE_LOG(LOG_FATAL, "DetectMyNeed new waitTimeDoCmd failed");
86         delete hUSB;
87         return false;
88     }
89     uv_timer_init(&hdcServer->loopMain, waitTimeDoCmd);
90     waitTimeDoCmd->data = hSession;
91     uv_timer_start(waitTimeDoCmd, hdcServer->UsbPreConnect, 0, DEVICE_CHECK_INTERVAL);
92     mapIgnoreDevice[sn] = HOST_USB_REGISTER;
93     delete hUSB;
94     return true;
95 }
96 
KickoutZombie(HSession hSession)97 void HdcHostUSB::KickoutZombie(HSession hSession)
98 {
99     HdcServer *ptrConnect = (HdcServer *)hSession->classInstance;
100     HUSB hUSB = hSession->hUSB;
101     if (!hUSB->devHandle) {
102         WRITE_LOG(LOG_WARN, "KickoutZombie devHandle:%p isDead:%d", hUSB->devHandle, hSession->isDead);
103         return;
104     }
105     if (LIBUSB_ERROR_NO_DEVICE != libusb_kernel_driver_active(hUSB->devHandle, hUSB->interfaceNumber)) {
106         return;
107     }
108     WRITE_LOG(LOG_WARN, "KickoutZombie LIBUSB_ERROR_NO_DEVICE serialNumber:%s", hUSB->serialNumber.c_str());
109     ptrConnect->FreeSession(hSession->sessionId);
110 }
111 
RemoveIgnoreDevice(string & mountInfo)112 void HdcHostUSB::RemoveIgnoreDevice(string &mountInfo)
113 {
114     if (mapIgnoreDevice.count(mountInfo)) {
115         mapIgnoreDevice.erase(mountInfo);
116     }
117 }
118 
ReviewUsbNodeLater(string & nodeKey)119 void HdcHostUSB::ReviewUsbNodeLater(string &nodeKey)
120 {
121     HdcServer *hdcServer = (HdcServer *)clsMainBase;
122     // add to ignore list
123     mapIgnoreDevice[nodeKey] = HOST_USB_IGNORE;
124     int delayRemoveFromList = DEVICE_CHECK_INTERVAL * MINOR_TIMEOUT;  // wait little time for daemon reinit
125     Base::DelayDo(&hdcServer->loopMain, delayRemoveFromList, 0, nodeKey, nullptr,
126                   [this](const uint8_t flag, string &msg, const void *) -> void { RemoveIgnoreDevice(msg); });
127 }
128 
WatchUsbNodeChange(uv_timer_t * handle)129 void HdcHostUSB::WatchUsbNodeChange(uv_timer_t *handle)
130 {
131     HdcHostUSB *thisClass = (HdcHostUSB *)handle->data;
132     HdcServer *ptrConnect = (HdcServer *)thisClass->clsMainBase;
133     libusb_device **devs = nullptr;
134     libusb_device *dev = nullptr;
135     // kick zombie
136     ptrConnect->EnumUSBDeviceRegister(KickoutZombie);
137     // find new
138     ssize_t cnt = libusb_get_device_list(thisClass->ctxUSB, &devs);
139     if (cnt < 0) {
140         WRITE_LOG(LOG_FATAL, "Failed to get device list");
141         return;
142     }
143     WRITE_LOG(LOG_DEBUG, "WatchUsbNodeChange cnt: %lu", cnt);
144     int i = 0;
145     // linux replug devid increment,windows will be not
146     while ((dev = devs[i++]) != nullptr) {  // must postfix++
147         string szTmpKey = Base::StringFormat("%d-%d", libusb_get_bus_number(dev), libusb_get_device_address(dev));
148         // check is in ignore list
149         UsbCheckStatus statusCheck = thisClass->mapIgnoreDevice[szTmpKey];
150         if (statusCheck == HOST_USB_IGNORE || statusCheck == HOST_USB_REGISTER) {
151             continue;
152         }
153         WRITE_LOG(LOG_DEBUG, "WatchUsbNodeChange szTmpKey:%s", szTmpKey.c_str());
154         string sn = szTmpKey;
155         if (!thisClass->DetectMyNeed(dev, sn)) {
156             thisClass->ReviewUsbNodeLater(szTmpKey);
157         }
158     }
159     libusb_free_device_list(devs, 1);
160 }
161 
162 // Main thread USB operates in this thread
UsbWorkThread(void * arg)163 void HdcHostUSB::UsbWorkThread(void *arg)
164 {
165     HdcHostUSB *thisClass = (HdcHostUSB *)arg;
166     constexpr uint8_t USB_HANDLE_TIMEOUT = 30;  // second
167     while (thisClass->modRunning) {
168         struct timeval zerotime;
169         zerotime.tv_sec = USB_HANDLE_TIMEOUT;
170         zerotime.tv_usec = 0;  // if == 0,windows will be high CPU load
171         libusb_handle_events_timeout(thisClass->ctxUSB, &zerotime);
172     }
173     WRITE_LOG(LOG_DEBUG, "Host Sessionbase usb workthread finish");
174 }
175 
StartupUSBWork()176 int HdcHostUSB::StartupUSBWork()
177 {
178     // Because libusb(winusb backend) does not support hotplug under win32, we use list mode for all platforms
179     WRITE_LOG(LOG_DEBUG, "USBHost loopfind mode");
180     devListWatcher.data = this;
181     uv_timer_start(&devListWatcher, WatchUsbNodeChange, 0, DEVICE_CHECK_INTERVAL);
182     // Running pendding in independent threads does not significantly improve the efficiency
183     uv_thread_create(&threadUsbWork, UsbWorkThread, this);
184     return 0;
185 }
186 
CheckDescriptor(HUSB hUSB,libusb_device_descriptor & desc)187 int HdcHostUSB::CheckDescriptor(HUSB hUSB, libusb_device_descriptor& desc)
188 {
189     char serialNum[BUF_SIZE_MEDIUM] = "";
190     int childRet = 0;
191     uint8_t curBus = libusb_get_bus_number(hUSB->device);
192     uint8_t curDev = libusb_get_device_address(hUSB->device);
193     hUSB->busId = curBus;
194     hUSB->devId = curDev;
195     if (libusb_get_device_descriptor(hUSB->device, &desc)) {
196         WRITE_LOG(LOG_WARN, "CheckDescriptor libusb_get_device_descriptor failed %d-%d", curBus, curDev);
197         return -1;
198     }
199     // Get the serial number of the device, if there is no serial number, use the ID number to replace
200     // If the device is not in time, occasionally can't get it, this is determined by the external factor, cannot be
201     // changed. LIBUSB_SUCCESS
202     childRet = libusb_get_string_descriptor_ascii(hUSB->devHandle, desc.iSerialNumber, (uint8_t *)serialNum,
203                                                   sizeof(serialNum));
204     if (childRet < 0) {
205         WRITE_LOG(LOG_WARN, "CheckDescriptor libusb_get_string_descriptor_ascii failed %d-%d", curBus, curDev);
206         return -1;
207     } else {
208         hUSB->serialNumber = serialNum;
209     }
210     WRITE_LOG(LOG_DEBUG, "CheckDescriptor busId-devId:%d-%d serialNum:%s", curBus, curDev, serialNum);
211     return 0;
212 }
213 
214 // hSession can be null
UpdateUSBDaemonInfo(HUSB hUSB,HSession hSession,uint8_t connStatus)215 void HdcHostUSB::UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus)
216 {
217     // add to list
218     HdcServer *pServer = (HdcServer *)clsMainBase;
219     HdcDaemonInformation di;
220     di.connectKey = hUSB->serialNumber;
221     di.connType = CONN_USB;
222     di.connStatus = connStatus;
223     di.hSession = hSession;
224     di.usbMountPoint = "";
225     di.usbMountPoint = Base::StringFormat("%d-%d", hUSB->busId, hUSB->devId);
226 
227     HDaemonInfo pDi = nullptr;
228     HDaemonInfo hdiNew = &di;
229     pServer->AdminDaemonMap(OP_QUERY, hUSB->serialNumber, pDi);
230     if (!pDi) {
231         pServer->AdminDaemonMap(OP_ADD, hUSB->serialNumber, hdiNew);
232     } else {
233         pServer->AdminDaemonMap(OP_UPDATE, hUSB->serialNumber, hdiNew);
234     }
235 }
236 
IsDebuggableDev(const struct libusb_interface_descriptor * ifDescriptor)237 bool HdcHostUSB::IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor)
238 {
239     constexpr uint8_t harmonyEpNum = 2;
240     constexpr uint8_t harmonyClass = 0xff;
241     constexpr uint8_t harmonySubClass = 0x50;
242     constexpr uint8_t harmonyProtocol = 0x01;
243 
244     if (ifDescriptor->bInterfaceClass != harmonyClass || ifDescriptor->bInterfaceSubClass != harmonySubClass
245         || ifDescriptor->bInterfaceProtocol != harmonyProtocol) {
246         WRITE_LOG(LOG_DEBUG, "IsDebuggableDev false bInterfaceClass:%d bInterfaceSubClass:%d bInterfaceProtocol:%d",
247                   ifDescriptor->bInterfaceClass, ifDescriptor->bInterfaceSubClass, ifDescriptor->bInterfaceProtocol);
248         return false;
249     }
250     if (ifDescriptor->bNumEndpoints != harmonyEpNum) {
251         WRITE_LOG(LOG_DEBUG, "IsDebuggableDev false bNumEndpoints:%d", ifDescriptor->bNumEndpoints);
252         return false;
253     }
254     return true;
255 }
256 
CheckActiveConfig(libusb_device * device,HUSB hUSB,libusb_device_descriptor & desc)257 int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB, libusb_device_descriptor& desc)
258 {
259     unsigned int j = 0;
260     struct libusb_config_descriptor *descConfig = nullptr;
261     int ret = libusb_get_active_config_descriptor(device, &descConfig);
262     if (ret != 0)
263     {
264 #ifdef HOST_MAC
265         if ((desc.bDeviceClass == 0xFF)
266             && (desc.bDeviceSubClass == 0xFF)
267             && (desc.bDeviceProtocol == 0xFF))
268         {
269             ret = libusb_set_configuration(hUSB->devHandle, 1);
270             if (ret != 0)
271             {
272                 WRITE_LOG(LOG_WARN, "set config failed ret:%d", ret);
273                 return -1;
274             }
275         }
276 
277         ret = libusb_get_active_config_descriptor(device, &descConfig);
278         if (ret != 0)
279         {
280 #endif
281             return -1;
282         }
283 #ifdef HOST_MAC
284     }
285 #endif
286 
287     ret = -1;
288     for (j = 0; j < descConfig->bNumInterfaces; ++j) {
289         const struct libusb_interface *interface = &descConfig->interface[j];
290         if (interface->num_altsetting >= 1) {
291             const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0];
292             if (!IsDebuggableDev(ifDescriptor)) {
293                 continue;
294             }
295             WRITE_LOG(LOG_DEBUG, "CheckActiveConfig IsDebuggableDev passed and then check endpoint attr");
296             hUSB->interfaceNumber = ifDescriptor->bInterfaceNumber;
297             unsigned int k = 0;
298             for (k = 0; k < ifDescriptor->bNumEndpoints; ++k) {
299                 const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k];
300                 if ((ep_desc->bmAttributes & 0x03) == LIBUSB_TRANSFER_TYPE_BULK) {
301                     if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
302                         hUSB->hostBulkIn.endpoint = ep_desc->bEndpointAddress;
303                         hUSB->hostBulkIn.bulkInOut = true;
304                     } else {
305                         hUSB->hostBulkOut.endpoint = ep_desc->bEndpointAddress;
306                         hUSB->wMaxPacketSizeSend = ep_desc->wMaxPacketSize;
307                         hUSB->hostBulkOut.bulkInOut = false;
308                     }
309                 }
310             }
311             if (hUSB->hostBulkIn.endpoint == 0 || hUSB->hostBulkOut.endpoint == 0) {
312                 break;
313             }
314             ret = 0;
315         }
316     }
317     libusb_free_config_descriptor(descConfig);
318     return ret;
319 }
320 
321 // multi-thread calll
CancelUsbIo(HSession hSession)322 void HdcHostUSB::CancelUsbIo(HSession hSession)
323 {
324     WRITE_LOG(LOG_DEBUG, "HostUSB CancelUsbIo, ref:%u", uint32_t(hSession->ref));
325     HUSB hUSB = hSession->hUSB;
326     std::unique_lock<std::mutex> lock(hUSB->lockDeviceHandle);
327     if (!hUSB->hostBulkIn.isShutdown) {
328         if (!hUSB->hostBulkIn.isComplete) {
329             libusb_cancel_transfer(hUSB->hostBulkIn.transfer);
330             hUSB->hostBulkIn.cv.notify_one();
331         } else {
332             hUSB->hostBulkIn.isShutdown = true;
333         }
334     }
335     if (!hUSB->hostBulkOut.isShutdown) {
336         if (!hUSB->hostBulkOut.isComplete) {
337             libusb_cancel_transfer(hUSB->hostBulkOut.transfer);
338             hUSB->hostBulkOut.cv.notify_one();
339         } else {
340             hUSB->hostBulkOut.isShutdown = true;
341         }
342     }
343 }
344 
345 // 3rd write child-hdc-workthread
346 // no use uvwrite, raw write to socketpair's fd
UsbToHdcProtocol(uv_stream_t * stream,uint8_t * appendData,int dataSize)347 int HdcHostUSB::UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int dataSize)
348 {
349     HSession hSession = (HSession)stream->data;
350     unsigned int fd = hSession->dataFd[STREAM_MAIN];
351     fd_set fdSet;
352     struct timeval timeout = { 3, 0 };
353     FD_ZERO(&fdSet);
354     FD_SET(fd, &fdSet);
355     int index = 0;
356     int childRet = 0;
357 
358     while (index < dataSize) {
359         if ((childRet = select(fd + 1, NULL, &fdSet, NULL, &timeout)) <= 0) {
360             constexpr int bufSize = 1024;
361             char buf[bufSize] = { 0 };
362 #ifdef _WIN32
363             strerror_s(buf, bufSize, errno);
364 #else
365             strerror_r(errno, buf, bufSize);
366 #endif
367             WRITE_LOG(LOG_FATAL, "select error:%d [%s][%d]", errno, buf, childRet);
368             break;
369         }
370         childRet = send(fd, (const char *)appendData + index, dataSize - index, 0);
371         if (childRet < 0) {
372             constexpr int bufSize = 1024;
373             char buf[bufSize] = { 0 };
374 #ifdef _WIN32
375             strerror_s(buf, bufSize, errno);
376 #else
377             strerror_r(errno, buf, bufSize);
378 #endif
379             WRITE_LOG(LOG_FATAL, "UsbToHdcProtocol senddata err:%d [%s]", errno, buf);
380             break;
381         }
382         index += childRet;
383     }
384     if (index != dataSize) {
385         WRITE_LOG(LOG_FATAL, "UsbToHdcProtocol partialsenddata err:%d [%d]", index, dataSize);
386         return ERR_IO_FAIL;
387     }
388     return index;
389 }
390 
USBBulkCallback(struct libusb_transfer * transfer)391 void LIBUSB_CALL HdcHostUSB::USBBulkCallback(struct libusb_transfer *transfer)
392 {
393     auto *ep = static_cast<HostUSBEndpoint *>(transfer->user_data);
394     std::unique_lock<std::mutex> lock(ep->mutexIo);
395     bool retrySumit = false;
396     int childRet = 0;
397     do {
398         if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
399             WRITE_LOG(LOG_FATAL, "USBBulkCallback1 failed, ret:%d", transfer->status);
400             break;
401         }
402         if (!ep->bulkInOut && transfer->actual_length != transfer->length) {
403             transfer->length -= transfer->actual_length;
404             transfer->buffer += transfer->actual_length;
405             retrySumit = true;
406             break;
407         }
408     } while (false);
409     while (retrySumit) {
410         childRet = libusb_submit_transfer(transfer);
411         if (childRet != 0) {
412             WRITE_LOG(LOG_FATAL, "USBBulkCallback2 failed, ret:%d", childRet);
413             transfer->status = LIBUSB_TRANSFER_ERROR;
414             break;
415         }
416         return;
417     }
418     ep->isComplete = true;
419     ep->cv.notify_one();
420 }
421 
SubmitUsbBio(HSession hSession,bool sendOrRecv,uint8_t * buf,int bufSize)422 int HdcHostUSB::SubmitUsbBio(HSession hSession, bool sendOrRecv, uint8_t *buf, int bufSize)
423 {
424     HUSB hUSB = hSession->hUSB;
425     int timeout = 0;
426     int childRet = 0;
427     int ret = ERR_IO_FAIL;
428     HostUSBEndpoint *ep = nullptr;
429 
430     if (sendOrRecv) {
431         timeout = GLOBAL_TIMEOUT * TIME_BASE;
432         ep = &hUSB->hostBulkOut;
433     } else {
434         timeout = 0;  // infinity
435         ep = &hUSB->hostBulkIn;
436     }
437     hUSB->lockDeviceHandle.lock();
438     ep->isComplete = false;
439     do {
440         std::unique_lock<std::mutex> lock(ep->mutexIo);
441         libusb_fill_bulk_transfer(ep->transfer, hUSB->devHandle, ep->endpoint, buf, bufSize, USBBulkCallback, ep,
442                                   timeout);
443         childRet = libusb_submit_transfer(ep->transfer);
444         hUSB->lockDeviceHandle.unlock();
445         if (childRet < 0) {
446             WRITE_LOG(LOG_FATAL, "SubmitUsbBio libusb_submit_transfer failed, ret:%d", childRet);
447             break;
448         }
449         ep->cv.wait(lock, [ep]() { return ep->isComplete; });
450         if (ep->transfer->status != 0) {
451             WRITE_LOG(LOG_FATAL, "SubmitUsbBio transfer failed, status:%d", ep->transfer->status);
452             break;
453         }
454         ret = ep->transfer->actual_length;
455     } while (false);
456     return ret;
457 }
458 
BeginUsbRead(HSession hSession)459 void HdcHostUSB::BeginUsbRead(HSession hSession)
460 {
461     HUSB hUSB = hSession->hUSB;
462     hUSB->hostBulkIn.isShutdown = false;
463     hUSB->hostBulkOut.isShutdown = false;
464     ++hSession->ref;
465     // loop read
466     std::thread([this, hSession, hUSB]() {
467         int childRet = 0;
468         int nextReadSize = 0;
469         while (!hSession->isDead) {
470             // if readIO < wMaxPacketSizeSend, libusb report overflow
471             nextReadSize = (childRet < hUSB->wMaxPacketSizeSend ? hUSB->wMaxPacketSizeSend
472                                                                 : std::min(childRet, Base::GetUsbffsBulkSize()));
473             childRet = SubmitUsbBio(hSession, false, hUSB->hostBulkIn.buf, nextReadSize);
474             if (childRet < 0) {
475                 WRITE_LOG(LOG_FATAL, "Read usb failed, ret:%d", childRet);
476                 break;
477             }
478             childRet = SendToHdcStream(hSession, reinterpret_cast<uv_stream_t *>(&hSession->dataPipe[STREAM_MAIN]),
479                                        hUSB->hostBulkIn.buf, childRet);
480             if (childRet < 0) {
481                 WRITE_LOG(LOG_FATAL, "SendToHdcStream failed, ret:%d", childRet);
482                 break;
483             }
484         }
485         --hSession->ref;
486         auto server = reinterpret_cast<HdcServer *>(clsMainBase);
487         hUSB->hostBulkIn.isShutdown = true;
488         server->FreeSession(hSession->sessionId);
489         WRITE_LOG(LOG_DEBUG, "Usb loop read finish");
490     }).detach();
491 }
492 
493 // ==0 Represents new equipment and is what we need,<0  my need
OpenDeviceMyNeed(HUSB hUSB)494 int HdcHostUSB::OpenDeviceMyNeed(HUSB hUSB)
495 {
496     libusb_device *device = hUSB->device;
497     int ret = -1;
498     if (LIBUSB_SUCCESS != libusb_open(device, &hUSB->devHandle)) {
499         return -100;
500     }
501     while (modRunning) {
502         libusb_device_handle *handle = hUSB->devHandle;
503         struct libusb_device_descriptor desc;
504         if (CheckDescriptor(hUSB, desc)) {
505             WRITE_LOG(LOG_WARN, "OpenDeviceMyNeed CheckDescriptor break");
506             break;
507         }
508         if (CheckActiveConfig(device, hUSB, desc)) {
509             WRITE_LOG(LOG_WARN, "OpenDeviceMyNeed CheckActiveConfig break");
510             break;
511         }
512         // USB filter rules are set according to specific device pedding device
513         ret = libusb_claim_interface(handle, hUSB->interfaceNumber);
514         break;
515     }
516     if (ret) {
517         // not my need device, release the device
518         libusb_close(hUSB->devHandle);
519         hUSB->devHandle = nullptr;
520     }
521     WRITE_LOG(LOG_DEBUG, "OpenDeviceMyNeed ret:%d", ret);
522     return ret;
523 }
524 
SendUSBRaw(HSession hSession,uint8_t * data,const int length)525 int HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length)
526 {
527     int ret = ERR_GENERIC;
528     HdcSessionBase *server = reinterpret_cast<HdcSessionBase *>(hSession->classInstance);
529     ++hSession->ref;
530     ret = SubmitUsbBio(hSession, true, data, length);
531     if (ret < 0) {
532         WRITE_LOG(LOG_FATAL, "Send usb failed, ret:%d", ret);
533         CancelUsbIo(hSession);
534         hSession->hUSB->hostBulkOut.isShutdown = true;
535         server->FreeSession(hSession->sessionId);
536     }
537     --hSession->ref;
538     return ret;
539 }
540 
FindDeviceByID(HUSB hUSB,const char * usbMountPoint,libusb_context * ctxUSB)541 bool HdcHostUSB::FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB)
542 {
543     libusb_device **listDevices = nullptr;
544     bool ret = false;
545     char tmpStr[BUF_SIZE_TINY] = "";
546     int busNum = 0;
547     int devNum = 0;
548     int curBus = 0;
549     int curDev = 0;
550 
551     int device_num = libusb_get_device_list(ctxUSB, &listDevices);
552     if (device_num <= 0) {
553         libusb_free_device_list(listDevices, 1);
554         return false;
555     }
556     if (strchr(usbMountPoint, '-') && EOK == strcpy_s(tmpStr, sizeof(tmpStr), usbMountPoint)) {
557         *strchr(tmpStr, '-') = '\0';
558         busNum = atoi(tmpStr);
559         devNum = atoi(tmpStr + strlen(tmpStr) + 1);
560     } else
561         return false;
562 
563     int i = 0;
564     for (i = 0; i < device_num; ++i) {
565         struct libusb_device_descriptor desc;
566         if (LIBUSB_SUCCESS != libusb_get_device_descriptor(listDevices[i], &desc)) {
567             break;
568         }
569         curBus = libusb_get_bus_number(listDevices[i]);
570         curDev = libusb_get_device_address(listDevices[i]);
571         if ((curBus == busNum && curDev == devNum)) {
572             hUSB->device = listDevices[i];
573             int childRet = OpenDeviceMyNeed(hUSB);
574             if (!childRet) {
575                 ret = true;
576             }
577             break;
578         }
579     }
580     libusb_free_device_list(listDevices, 1);
581     return ret;
582 }
583 
ReadyForWorkThread(HSession hSession)584 bool HdcHostUSB::ReadyForWorkThread(HSession hSession)
585 {
586     HdcUSBBase::ReadyForWorkThread(hSession);
587     return true;
588 };
589 
590 // Determines that daemonInfo must have the device
ConnectDetectDaemon(const HSession hSession,const HDaemonInfo pdi)591 HSession HdcHostUSB::ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi)
592 {
593     HdcServer *pServer = (HdcServer *)clsMainBase;
594     HUSB hUSB = hSession->hUSB;
595     hUSB->usbMountPoint = pdi->usbMountPoint;
596     hUSB->ctxUSB = ctxUSB;
597     if (!FindDeviceByID(hUSB, hUSB->usbMountPoint.c_str(), hUSB->ctxUSB)) {
598         pServer->FreeSession(hSession->sessionId);
599         return nullptr;
600     }
601     UpdateUSBDaemonInfo(hUSB, hSession, STATUS_CONNECTED);
602     BeginUsbRead(hSession);
603     hUSB->usbMountPoint = pdi->usbMountPoint;
604     WRITE_LOG(LOG_DEBUG, "HSession HdcHostUSB::ConnectDaemon");
605 
606     Base::StartWorkThread(&pServer->loopMain, pServer->SessionWorkThread, Base::FinishWorkThread, hSession);
607     // wait for thread up
608     while (hSession->childLoop.active_handles == 0) {
609         uv_sleep(1);
610     }
611     auto ctrl = pServer->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
612     Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size());
613     return hSession;
614 }
615 }  // namespace Hdc
616