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