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