• 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_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