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