1 /*
2 * Copyright (c) 2025 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
16 #include "libusb_serial.h"
17 #include <cerrno>
18 #include <hdf_base.h>
19 #include <dirent.h>
20 #include <hdf_log.h>
21 #include <sys/mman.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <sstream>
25 #include <climits>
26 #include <iostream>
27 #include <filesystem>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <cstring>
32 #include <string>
33 #include <chrono>
34 #include "usbd_wrapper.h"
35 #include "securec.h"
36
37 namespace OHOS {
38 namespace HDI {
39 namespace Usb {
40 namespace Serial {
41 namespace V1_0 {
42
43 #define TARGET_INTERFACE 0xFF
44 #define MAX_TRANS_DATA_SIZE 8192
45 #define ENABLE_UNREF 1
46 #define TRANSFER_TIMEOUT 1000
47 #define DIRECT_NUM 2
48 #define TRANSFER_CONTROL_OUT_CODE 0x20
49 #define TRANSFER_CONTROL_IN_CODE 0x21
50 #define RETRY_TIMEOUT 10
51 #define RETRY_NUM 5
52 #define BUFFER_SIZE 256
53 #define SERIAL_NUM 256
54 #define ERR_CODE_IOEXCEPTION (-5)
55 #define ERR_CODE_DEVICENOTOPEN (-6)
56 #define OUTPUT_WIDTH 2
57
58 static const std::string BUS_NUM_STR = "/busnum";
59 static const std::string DEV_NUM_STR = "/devnum";
60 static const std::string DEV_FILENAME_PREFIX = "ttyUSB";
61 static const std::string DEV_PATH_PREFIX = "/sys/bus/usb-serial/devices";
62 static const std::string TTYUSB_PATH = "/sys/class/tty";
63
64 namespace fs = std::filesystem;
65
GetInstance()66 LibusbSerial &LibusbSerial::GetInstance()
67 {
68 static LibusbSerial instance;
69 return instance;
70 }
71
LibusbSerial()72 LibusbSerial::LibusbSerial(): ctx_(nullptr), running_(true)
73 {
74 HDF_LOGI("%{public}s: enter SerialUSBWrapper initialization.", __func__);
75
76 int ret = libusb_init(&ctx_);
77 if (ret != LIBUSB_SUCCESS) {
78 HDF_LOGE("%{public}s: Failed to initialize libusb: %{public}d", __func__, ret);
79 ctx_ = nullptr;
80
81 return;
82 }
83
84 if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
85 HDF_LOGE("%{public}s: Hotplug capability is not supported on this platform", __func__);
86 libusb_exit(ctx_);
87 ctx_ = nullptr;
88
89 return;
90 }
91
92 ret = libusb_hotplug_register_callback(ctx_,
93 static_cast<libusb_hotplug_event>(
94 LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
95 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
96 LIBUSB_HOTPLUG_NO_FLAGS,
97 LIBUSB_HOTPLUG_MATCH_ANY,
98 LIBUSB_HOTPLUG_MATCH_ANY,
99 LIBUSB_HOTPLUG_MATCH_ANY,
100 HotplugCallback,
101 this,
102 &hotplug_handle_);
103 if (ret != LIBUSB_SUCCESS) {
104 HDF_LOGE("%{public}s: Failed to register hotplug callback: %{public}d", __func__, ret);
105 libusb_exit(ctx_);
106 ctx_ = nullptr;
107
108 return;
109 }
110
111 GetExistedDevices();
112 event_thread_ = std::thread(&LibusbSerial::EventHandlingThread, this);
113 HDF_LOGI("%{public}s: SerialUSBWrapper initialization completed.", __func__);
114 }
115
~LibusbSerial()116 LibusbSerial::~LibusbSerial()
117 {
118 HDF_LOGI("%{public}s: enter Destroying SerialUSBWrapper.", __func__);
119 running_ = false;
120 if (event_thread_.joinable()) {
121 event_thread_.join();
122 }
123 if (ctx_) {
124 libusb_hotplug_deregister_callback(ctx_, hotplug_handle_);
125 }
126
127 std::lock_guard<std::mutex> lock(map_mutex_);
128 for (auto& pair : devices_) {
129 if (pair.second.handle) {
130 libusb_close(pair.second.handle);
131 pair.second.handle = nullptr;
132 }
133 }
134
135 devices_.clear();
136
137 if (ctx_) {
138 libusb_exit(ctx_);
139 ctx_ = nullptr;
140 }
141
142 HDF_LOGI("%{public}s: SerialUSBWrapper destroyed.", __func__);
143 }
144
GetExistedDevices()145 void LibusbSerial::GetExistedDevices()
146 {
147 libusb_device** device_list = nullptr;
148 ssize_t count = libusb_get_device_list(ctx_, &device_list);
149 if (count < 0) {
150 HDF_LOGE("%{public}s: Failed to get device list: %{public}d", __func__, (int)count);
151 return;
152 }
153
154 for (ssize_t idx = 0; idx < count; ++idx) {
155 libusb_device* device = device_list[idx];
156 struct libusb_device_descriptor desc;
157 int ret = libusb_get_device_descriptor(device, &desc);
158 if (ret < 0) {
159 continue;
160 }
161 if (desc.bDeviceClass == LIBUSB_CLASS_HUB) {
162 continue;
163 }
164 HandleDeviceArrival(device);
165 }
166
167 libusb_free_device_list(device_list, ENABLE_UNREF);
168 HDF_LOGI("%{public}s: Existing devices enumeration completed. device count: %{public}zu", __func__, count);
169 }
170
SerialOpen(int32_t num)171 int32_t LibusbSerial::SerialOpen(int32_t num)
172 {
173 HDF_LOGI("%{public}s: enter SerialOpen called for num: %{public}d.", __func__, num);
174 std::lock_guard<std::mutex> lock(map_mutex_);
175 for (auto& pair : devices_) {
176 if (pair.second.num == num) {
177 if (pair.second.isOpen) {
178 return HDF_SUCCESS;
179 }
180 pair.second.isOpen = true;
181 return HDF_SUCCESS;
182 }
183 }
184 HDF_LOGE("%{public}s: Device not found: num = %{public}d", __func__, num);
185 return HDF_FAILURE;
186 }
187
SerialClose(int32_t num)188 int32_t LibusbSerial::SerialClose(int32_t num)
189 {
190 HDF_LOGI("%{public}s: enter SerialClose called for num: %{public}d.", __func__, num);
191 std::lock_guard<std::mutex> lock(map_mutex_);
192 for (auto& pair : devices_) {
193 if (pair.second.num == num) {
194 if (pair.second.isOpen) {
195 pair.second.isOpen = false;
196 HDF_LOGI("%{public}s: Device logically closed: num = %{public}d", __func__, num);
197 }
198 return HDF_SUCCESS;
199 }
200 }
201 return HDF_SUCCESS;
202 }
203
GetSerialDeviceInfo(libusb_device * device,libusb_device_handle * handle,DeviceInfo & deviceInfo)204 int32_t LibusbSerial::GetSerialDeviceInfo(libusb_device* device, libusb_device_handle* handle, DeviceInfo &deviceInfo)
205 {
206 HDF_LOGI("%{public}s: enter GetSerialDeviceInfo.", __func__);
207 struct libusb_device_descriptor desc;
208 int result = -1;
209 result = libusb_get_device_descriptor(device, &desc);
210 if (result < 0) {
211 HDF_LOGE("%{public}s: get device descriptor error: %{public}d", __func__, result);
212 return HDF_FAILURE;
213 }
214
215 char serialNumber[BUFFER_SIZE] = {'\0'};
216 unsigned char serial[BUFFER_SIZE] = {'\0'};
217 if (handle && desc.iSerialNumber) {
218 HDF_LOGI("%{public}s: desc serialNum: %{public}hhu", __func__, desc.iSerialNumber);
219 result = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, serial, sizeof(serial));
220 }
221 if (result > 0) {
222 int n = snprintf_s(serialNumber, sizeof(serialNumber), sizeof(serialNumber)-1, "%s",
223 reinterpret_cast<char*>(serial));
224 if (n < 0) {
225 return HDF_FAILURE;
226 }
227 } else {
228 HDF_LOGE("%{public}s: get serial num error, result: %{public}d", __func__, result);
229 return HDF_FAILURE;
230 }
231
232 deviceInfo.vid = desc.idVendor;
233 deviceInfo.pid = desc.idProduct;
234 deviceInfo.busNum = libusb_get_bus_number(device);
235 deviceInfo.devAddr = libusb_get_device_address(device);
236 deviceInfo.serialNum = std::string(serialNumber);
237 return HDF_SUCCESS;
238 }
239
SerialGetPortList(std::vector<SerialPort> & portIds)240 int32_t LibusbSerial::SerialGetPortList(std::vector<SerialPort>& portIds)
241 {
242 HDF_LOGI("%{public}s: enter SerialGetPortList.", __func__);
243 std::lock_guard<std::mutex> lock(map_mutex_);
244 portIds.clear();
245 for (const std::pair<libusb_device*, DeviceHandleInfo>& device : devices_) {
246 SerialPort serialPort;
247 libusb_device* dev = device.first;
248 libusb_device_handle* handle = device.second.handle;
249
250 GetSerialDeviceInfo(dev, handle, serialPort.deviceInfo);
251 serialPort.portId = device.second.num;
252 portIds.push_back(serialPort);
253 }
254 return HDF_SUCCESS;
255 }
256
GetDeviceHandle(int portId)257 libusb_device_handle* LibusbSerial::GetDeviceHandle(int portId)
258 {
259 std::lock_guard guard(map_mutex_);
260 for (auto ite = devices_.cbegin(); ite != devices_.cend(); ++ite) {
261 if (ite->second.num == portId) {
262 return ite->second.handle;
263 }
264 }
265 return nullptr;
266 }
267
GetDevice(int portId)268 libusb_device* LibusbSerial::GetDevice(int portId)
269 {
270 std::lock_guard guard(map_mutex_);
271 for (auto ite = devices_.cbegin(); ite != devices_.cend(); ++ite) {
272 if (ite->second.num == portId) {
273 return ite->first;
274 }
275 }
276 return nullptr;
277 }
278
VectorToHex(const std::vector<uint8_t> & data)279 std::string VectorToHex(const std::vector<uint8_t>& data)
280 {
281 std::ostringstream oss;
282 oss << std::hex << std::setfill('0');
283 for (uint8_t byte : data) {
284 oss << std::setw(OUTPUT_WIDTH) << static_cast<int>(byte);
285 }
286 return oss.str();
287 }
288
SerialRead(int32_t portId,std::vector<uint8_t> & data,uint32_t size,uint32_t timeout)289 int32_t LibusbSerial::SerialRead(int32_t portId, std::vector<uint8_t>& data, uint32_t size, uint32_t timeout)
290 {
291 HDF_LOGI("%{public}s: enter serial read.", __func__);
292 libusb_device* device = GetDevice(portId);
293 if (device == nullptr) {
294 HDF_LOGE("%{public}s: get device failed", __func__);
295 return ERR_CODE_IOEXCEPTION;
296 }
297 DeviceHandleInfo deviceHandleInfo = devices_[device];
298 if (!deviceHandleInfo.isOpen) {
299 HDF_LOGE("%{public}s: device not open", __func__);
300 return ERR_CODE_DEVICENOTOPEN;
301 }
302 int ret = 0;
303 int actualLength = 0;
304 uint8_t dataIn[MAX_TRANS_DATA_SIZE] = {0};
305
306 std::lock_guard<std::mutex> lock(writeMutex_);
307 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
308 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
309 libusb_detach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
310 ret = libusb_claim_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
311 if (ret < 0) {
312 HDF_LOGE("%{public}s: libusb claim failed, ret:%{public}d", __func__, ret);
313 return HDF_FAILURE;
314 }
315 ret = 0;
316 ret = libusb_bulk_transfer(deviceHandleInfo.handle,
317 deviceHandleInfo.intputEndpointAddr, dataIn, size, &actualLength, timeout);
318 if (ret < 0 && actualLength == 0) {
319 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
320 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
321 HDF_LOGE("%{public}s: read message failed, ret:%{public}d", __func__, ret);
322 return ret;
323 }
324 std::vector<uint8_t> vec(dataIn, dataIn + actualLength);
325 data.insert(data.end(), vec.begin(), vec.end());
326 std::string tempHexBuff = VectorToHex(vec);
327 HDF_LOGI("%{public}s: read msg : %{public}s", __func__, data.data());
328 HDF_LOGI("%{public}s: read msg hex : %{public}s", __func__, tempHexBuff.c_str());
329 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
330 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
331 return actualLength;
332 }
333
SerialWrite(int32_t portId,const std::vector<uint8_t> & data,uint32_t size,uint32_t timeout)334 int32_t LibusbSerial::SerialWrite(int32_t portId, const std::vector<uint8_t>& data, uint32_t size, uint32_t timeout)
335 {
336 HDF_LOGI("%{public}s: enter serial write.", __func__);
337 libusb_device* device = GetDevice(portId);
338 if (device == nullptr) {
339 HDF_LOGE("%{public}s: get device failed", __func__);
340 return ERR_CODE_IOEXCEPTION;
341 }
342
343 DeviceHandleInfo deviceHandleInfo = devices_[device];
344 if (!deviceHandleInfo.isOpen) {
345 HDF_LOGE("%{public}s: device not open", __func__);
346 return ERR_CODE_DEVICENOTOPEN;
347 }
348 int ret = 0;
349 int actualLength = 0;
350 const uint8_t* dataOut = data.data();
351 std::lock_guard<std::mutex> lock(writeMutex_);
352 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
353 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
354 libusb_detach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
355 ret = libusb_claim_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
356 if (ret < 0) {
357 HDF_LOGE("%{public}s: libusb claim failed, ret:%{public}d", __func__, ret);
358 return HDF_FAILURE;
359 }
360 HDF_LOGI("%{public}s: write msg : %{public}s", __func__, data.data());
361 ret = libusb_bulk_transfer(deviceHandleInfo.handle, deviceHandleInfo.outputEndpointAddr,
362 const_cast<uint8_t*>(dataOut), data.size(), &actualLength, timeout);
363 if (ret < 0) {
364 HDF_LOGE("%{public}s: write message failed, ret:%{public}d", __func__, ret);
365 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
366 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
367 return ret;
368 }
369 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
370 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
371 return actualLength;
372 }
373
GetEndPoint(DeviceHandleInfo * deviceHandleInfo)374 int LibusbSerial::GetEndPoint(DeviceHandleInfo *deviceHandleInfo)
375 {
376 int endpointNum = 0;
377 struct libusb_config_descriptor *config;
378 libusb_device *device = libusb_get_device(deviceHandleInfo->handle);
379
380 libusb_get_active_config_descriptor(device, &config);
381 for (int j = 0; j < config->bNumInterfaces; j++) {
382 const struct libusb_interface *interface = &config->interface[j];
383 const struct libusb_interface_descriptor *interfaceDesc = interface->altsetting;
384 if (interfaceDesc->bInterfaceClass != TARGET_INTERFACE) {
385 continue;
386 }
387 for (int k = 0; k < interfaceDesc->bNumEndpoints; k++) {
388 const struct libusb_endpoint_descriptor *endpoint = &interfaceDesc->endpoint[k];
389 if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
390 (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) {
391 deviceHandleInfo->interface = j;
392 deviceHandleInfo->intputEndpointAddr = endpoint->bEndpointAddress;
393 endpointNum++;
394 }
395 if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
396 (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
397 endpointNum++;
398 deviceHandleInfo->interface = j;
399 deviceHandleInfo->outputEndpointAddr = endpoint->bEndpointAddress;
400 }
401 }
402 }
403 libusb_free_config_descriptor(config);
404
405 return endpointNum != DIRECT_NUM ? HDF_FAILURE : HDF_SUCCESS;
406 }
407
SerialGetAttribute(int32_t portId,struct SerialAttribute & attribute)408 int32_t LibusbSerial::SerialGetAttribute(int32_t portId, struct SerialAttribute& attribute)
409 {
410 HDF_LOGI("%{public}s: enter GetAttribute msg", __func__);
411 libusb_device* device = GetDevice(portId);
412 if (device == nullptr) {
413 HDF_LOGE("%{public}s: libusb_device is null", __func__);
414 return HDF_FAILURE;
415 }
416 DeviceHandleInfo deviceHandleInfo = devices_[device];
417 if (!deviceHandleInfo.isOpen) {
418 HDF_LOGE("%{public}s: device not open", __func__);
419 return ERR_CODE_DEVICENOTOPEN;
420 }
421 int ret = 0;
422 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
423 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
424 libusb_detach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
425 ret = libusb_claim_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
426 if (ret < 0) {
427 HDF_LOGE("%{public}s: libusb claim failed, ret:%{public}d", __func__, ret);
428 return HDF_FAILURE;
429 }
430 unsigned char requestType = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE;
431 uint16_t index = 0;
432 uint16_t value = 0;
433 int length = sizeof(struct SerialAttribute);
434 ret = libusb_control_transfer(deviceHandleInfo.handle, requestType, TRANSFER_CONTROL_IN_CODE,
435 value, index, (unsigned char *)&attribute, length, TRANSFER_TIMEOUT);
436 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
437 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
438 HDF_LOGI("%{public}s: getattribute baudrate :%{public}d"
439 "databit :%{public}d stop :%{public}d parity :%{public}d", __func__, attribute.baudrate,
440 attribute.dataBits, attribute.stopBits, attribute.parity);
441 if (ret < 0) {
442 HDF_LOGE("%{public}s: libusb get attribute failed, ret:%{public}d", __func__, ret);
443 return HDF_FAILURE;
444 }
445 return HDF_SUCCESS;
446 }
447
SerialSetAttribute(int32_t portId,const struct SerialAttribute & attribute)448 int32_t LibusbSerial::SerialSetAttribute(int32_t portId, const struct SerialAttribute& attribute)
449 {
450 HDF_LOGI("%{public}s: setattribute baudrate :%{public}d"
451 "databit :%{public}d stop :%{public}d parity :%{public}d", __func__, attribute.baudrate,
452 attribute.dataBits, attribute.stopBits, attribute.parity);
453 HDF_LOGI("%{public}s: enter setAttribute msg", __func__);
454 libusb_device* device = GetDevice(portId);
455 if (device == nullptr) {
456 return HDF_FAILURE;
457 }
458 DeviceHandleInfo deviceHandleInfo = devices_[device];
459 if (!deviceHandleInfo.isOpen) {
460 HDF_LOGE("%{public}s: device not open", __func__);
461 return ERR_CODE_DEVICENOTOPEN;
462 }
463 int ret = 0;
464 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
465 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
466 libusb_detach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
467 ret = libusb_claim_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
468 if (ret < 0) {
469 HDF_LOGE("%{public}s: libusb claim failed, ret:%{public}d", __func__, ret);
470 return HDF_FAILURE;
471 }
472 unsigned char requestType = LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE;
473 uint16_t index = 0;
474 uint16_t value = 0;
475 int length = sizeof(struct SerialAttribute);
476 ret = libusb_control_transfer(deviceHandleInfo.handle, requestType, TRANSFER_CONTROL_OUT_CODE,
477 value, index, (unsigned char *)&attribute, length, TRANSFER_TIMEOUT);
478 libusb_release_interface(deviceHandleInfo.handle, deviceHandleInfo.interface);
479 libusb_attach_kernel_driver(deviceHandleInfo.handle, deviceHandleInfo.interface);
480 if (ret < 0) {
481 HDF_LOGE("%{public}s: libusb set attribute failed, ret:%{public}d", __func__, ret);
482 return HDF_FAILURE;
483 }
484 HDF_LOGI("%{public}s: set attribute success", __func__);
485 return HDF_SUCCESS;
486 }
487
488
HotplugCallback(libusb_context * ctx,libusb_device * device,libusb_hotplug_event event,void * user_data)489 int32_t LibusbSerial::HotplugCallback(libusb_context* ctx, libusb_device* device,
490 libusb_hotplug_event event, void* user_data)
491 {
492 LibusbSerial* self = static_cast<LibusbSerial*>(user_data);
493
494 if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
495 self->HandleDeviceArrival(device);
496 } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
497 self->HandleDeviceRemoval(device);
498 }
499
500 return HDF_SUCCESS;
501 }
502
HandleDeviceArrival(libusb_device * device)503 int32_t LibusbSerial::HandleDeviceArrival(libusb_device* device)
504 {
505 HDF_LOGI("%{public}s: Device arrival detected.", __func__);
506
507 struct libusb_device_descriptor desc;
508 int ret = libusb_get_device_descriptor(device, &desc);
509 if (ret < 0) {
510 HDF_LOGW("%{public}s: get device descriptor failed.", __func__);
511 return HDF_FAILURE;
512 }
513 if (desc.bDeviceClass == LIBUSB_CLASS_HUB) {
514 HDF_LOGE("%{public}s: hub device pass.", __func__);
515 return HDF_FAILURE;
516 }
517
518 std::lock_guard<std::mutex> lock(map_mutex_);
519 int num = -1;
520 int retry = RETRY_NUM;
521
522 while (retry-- > 0) {
523 HDF_LOGI("%{public}s: Attempting to get device number, retry count: %{public}d", __func__, (RETRY_NUM - retry));
524 num = GetPortIdByDevice(device);
525 if (num >= 0) {
526 break;
527 }
528 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_TIMEOUT));
529 }
530
531 if (num < 0) {
532 HDF_LOGE("%{public}s: Failed to find matching /dev/ttyUSBN for the device after retries", __func__);
533 return HDF_FAILURE;
534 }
535
536 libusb_device_handle* handle = nullptr;
537 ret = libusb_open(device, &handle);
538 if (ret != LIBUSB_SUCCESS) {
539 HDF_LOGE("%{public}s: Failed to open device: %{public}d", __func__, ret);
540 return HDF_FAILURE;
541 }
542
543 DeviceHandleInfo info;
544 info.num = num;
545 info.handle = handle;
546 info.isOpen = false;
547
548 if (GetEndPoint(&info) != HDF_SUCCESS) {
549 HDF_LOGE("%{public}s: get endpoint failed", __func__);
550 return HDF_FAILURE;
551 }
552
553 devices_[device] = info;
554
555 HDF_LOGI("%{public}s: Device arrived and opened: num = %{public}d", __func__, num);
556 return HDF_SUCCESS;
557 }
558
HandleDeviceRemoval(libusb_device * device)559 void LibusbSerial::HandleDeviceRemoval(libusb_device* device)
560 {
561 HDF_LOGI("%{public}s: Device removal detected.", __func__);
562 struct libusb_device_descriptor desc;
563 int ret = libusb_get_device_descriptor(device, &desc);
564 if (ret < 0) {
565 HDF_LOGW("%{public}s: get device descriptor failed.", __func__);
566 return;
567 }
568 if (desc.bDeviceClass == LIBUSB_CLASS_HUB) {
569 HDF_LOGE("%{public}s: hub device pass.", __func__);
570 return;
571 }
572 std::lock_guard<std::mutex> lock(map_mutex_);
573 auto it = devices_.find(device);
574 if (it == devices_.end()) {
575 HDF_LOGE("%{public}s: Device not found in map during removal.", __func__);
576 return;
577 }
578 if (it->second.handle) {
579 libusb_close(it->second.handle);
580 it->second.handle = nullptr;
581 }
582 int num = it->second.num;
583 devices_.erase(it);
584 HDF_LOGI("%{public}s: Device removed: num = %{public}d", __func__, num);
585 }
586
EventHandlingThread()587 void LibusbSerial::EventHandlingThread()
588 {
589 HDF_LOGI("%{public}s: enter Event handling thread.", __func__);
590 while (running_) {
591 int ret = libusb_handle_events_completed(ctx_, nullptr);
592 if (ret != LIBUSB_SUCCESS) {
593 HDF_LOGE("%{public}s: libusb_handle_events_completed failed: %{public}d", __func__, ret);
594 }
595 }
596 HDF_LOGI("%{public}s: Event handling thread end.", __func__);
597 }
598
GetTtyDevicePath(const std::string & ttyDevice)599 std::string GetTtyDevicePath(const std::string& ttyDevice)
600 {
601 HDF_LOGI("%{public}s : enter GetTtyDevicePath.", __func__);
602 std::string ttyPathStr = TTYUSB_PATH + "/" + ttyDevice;
603 fs::path ttyPath(ttyPathStr);
604 if (!fs::exists(ttyPath) || !fs::is_symlink(ttyPath)) {
605 HDF_LOGE("%{public}s: path %{public}s not exist", __func__, ttyPath.string().c_str());
606 return NULL;
607 }
608 fs::path realPath = fs::read_symlink(ttyPath);
609 std::string tempPath = ttyPath.parent_path().string() + "/" + realPath.string();
610 realPath = fs::weakly_canonical(fs::path(tempPath));
611 std::string targetPath = realPath.parent_path().parent_path().parent_path().parent_path().string();
612 return targetPath;
613 }
614
CheckTtyDeviceInfo(std::string ttyUsbPath,libusb_device * device)615 bool CheckTtyDeviceInfo(std::string ttyUsbPath, libusb_device* device)
616 {
617 HDF_LOGI("%{public}s : enter checkTtyDeviceInfo.", __func__);
618 int busnumFd = 0;
619 int devnumFd = 0;
620 busnumFd = open((ttyUsbPath + BUS_NUM_STR).c_str(), O_RDONLY);
621 if (busnumFd < 0) {
622 HDF_LOGE("%{public}s : open file failed. ret = %{public}s", __func__, strerror(errno));
623 close(busnumFd);
624 return false;
625 }
626 char busnumBuff[BUFFER_SIZE] = {'\0'};
627 ssize_t readBytes = read(busnumFd, busnumBuff, BUFFER_SIZE);
628 if (readBytes < 0) {
629 close(busnumFd);
630 return false;
631 }
632 devnumFd = open((ttyUsbPath + DEV_NUM_STR).c_str(), O_RDONLY);
633 if (devnumFd < 0) {
634 HDF_LOGE("%{public}s : open file failed. ret = %{public}s", __func__, strerror(errno));
635 close(devnumFd);
636 close(busnumFd);
637 return false;
638 }
639 char devnumBuff[BUFFER_SIZE] = {'\0'};
640 readBytes = read(devnumFd, devnumBuff, BUFFER_SIZE);
641 if (readBytes < 0) {
642 close(busnumFd);
643 close(devnumFd);
644 return false;
645 }
646 close(devnumFd);
647 close(busnumFd);
648 if (atoi(devnumBuff) == libusb_get_device_address(device) && atoi(busnumBuff) == libusb_get_bus_number(device)) {
649 return true;
650 }
651 return false;
652 }
653
GetPortIdByDevice(libusb_device * device)654 int32_t LibusbSerial::GetPortIdByDevice(libusb_device* device)
655 {
656 HDF_LOGI("%{public}s : enter GetPortIdByDevice.", __func__);
657 DIR* dir = opendir(DEV_PATH_PREFIX.c_str());
658 if (dir == nullptr) {
659 HDF_LOGI("%{public}s : dir is not existed %{public}s", __func__, strerror(errno));
660 return -1;
661 }
662 struct dirent* entry = nullptr;
663 while ((entry = readdir(dir)) != nullptr) {
664 if (strncmp(entry->d_name, DEV_FILENAME_PREFIX.c_str(), DEV_FILENAME_PREFIX.size()) == 0) {
665 std::string devName = entry->d_name;
666 std::string targetPath = GetTtyDevicePath(devName);
667 if (targetPath.size() == 0) {
668 continue;
669 }
670 if (CheckTtyDeviceInfo(targetPath, device)) {
671 closedir(dir);
672 int32_t target = atoi(devName.substr(DEV_FILENAME_PREFIX.size()).c_str());
673 return target;
674 }
675 }
676 }
677 closedir(dir);
678 HDF_LOGI("%{public}s : it's not a serial device", __func__);
679 return -1;
680 }
681 } // V1_0
682 } // Serial
683 } // Usb
684 } // HDI
685 } // OHOS
686