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