HarmonyOS 鸿蒙Next中libusb移植总结
HarmonyOS 鸿蒙Next中libusb移植总结
【背景知识】 Windows上使用OpenHarmony SDK交叉编译指导(https://gitcode.com/openharmony-sig/tpc_c_cplusplus/blob/master/docs/adapter_windows.md)。
【解决方案】 libusb可以移植到HarmoneyOS,但是libusb因为涉及到权限问题,必须通过应用层的usbManager(https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-usbmanager)获取到usb的句柄传到native层去使用。参考外设扩展驱动开发指导(https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/driverextensionability#%E5%BA%94%E7%94%A8%E7%AD%BE%E5%90%8D)中的ohos.permission.ACCESS_EXTENSIONAL_DEVICE_DRIVER权限。
libusb集成到应用hap,可参考:libusb集成到应用hap(https://gitcode.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/libusb/docs/hap_integrate.md),
编译产物也适用于HarmonyOS Next。
示例代码如下:
import { hilog } from '@kit.PerformanceAnalysisKit';
import testNapi from 'libentry.so';
import { usbManager } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
showToast(msg: string) {
promptAction.showToast({
message: msg,
duration: 1500,
});
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
let deviceList: Array<usbManager.USBDevice> = usbManager.getDevices();
if (deviceList.length <= 0) {
this.showToast('未发现龙脉Ukey!');
return;
}
console.log(`devicesList = ${JSON.stringify(deviceList)}`);
let find = false;
let index = 0;
for (let dev of deviceList) {
if (dev.vendorId == 1372) {
if (!usbManager.hasRight(dev.name)) {
usbManager.requestRight(dev.name);
}
find = true;
break;
}
index++;
}
let devicepipe: usbManager.USBDevicePipe = usbManager.connectDevice(deviceList[index]);
let fd: number = usbManager.getFileDescriptor(devicepipe);
testNapi.skf_TestLed(fd);
this.showToast(
index + " : " + fd + " " + deviceList[0].vendorId + " " + deviceList[index].vendorId
);
});
}
.width('100%')
}
.height('100%');
}
}
static napi_value NAPI_Global_skf_TestLed(napi_env env, napi_callback_info info) {
napi_value result;
size_t argc = 1;
napi_value argv;
napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
int32_t fd = 0;
napi_get_value_int32(env, argv, &fd);
OH_LOG_INFO(LOG_APP, "fd: %{public}d", fd);
static libusb_context *ctx = NULL;
if (ctx == NULL) {
struct libusb_init_option options[] = {
{
.option = LIBUSB_OPTION_NO_DEVICE_DISCOVERY,
.value = { .ival = NULL },
},
};
OH_LOG_INFO(LOG_APP, "%{public}s %{public}s", "libusb_init1", "start");
int r = libusb_init_context(&ctx, options, 1);
OH_LOG_INFO(LOG_APP, "%{public}s %{public}d", "libusb_init2", r);
if (r < 0) {
OH_LOG_INFO(LOG_APP, "%{public}s %d", "libusb_initfail", libusb_error_name(r));
}
}
libusb_device_handle *handle = NULL;
int r = libusb_wrap_sys_device(ctx, (intptr_t)fd, &handle);
OH_LOG_INFO(LOG_APP, "%{public}s %{public}d", "libusb_wrap_sys_device", r);
if (r == 0) {
OH_LOG_INFO(LOG_APP, "%{public}s", "libusb_wrap_sys_device ok");
}
napi_get_undefined(env, &result);
// 获取设备列表
libusb_device **devices;
ssize_t cnt = libusb_get_device_list(ctx, &devices);
if (cnt < 0) {
std::cerr << "Failed to get device list: " << libusb_error_name(cnt) << std::endl;
libusb_exit(ctx);
}
// 遍历设备列表并获取第一个设备
for (ssize_t i = 0; i < cnt; i++) {
libusb_device *device = devices[i];
libusb_device_descriptor desc;
r = libusb_get_device_descriptor(device, &desc);
if (r < 0) {
std::cerr << "Failed to get device descriptor: " << libusb_error_name(r) << std::endl;
continue;
}
// 打印设备信息
std::cout << "Device " << i << ": ID "
<< std::hex << desc.idVendor << ":"
<< desc.idProduct << std::dec << std::endl;
// 打开设备
libusb_device_handle *handle;
r = libusb_open(device, &handle);
if (r != 0) {
std::cerr << "Failed to open device: " << libusb_error_name(r) << std::endl;
continue;
}
// 关闭设备
libusb_close(handle);
break; // 只处理第一个设备
}
// 释放设备列表
libusb_free_device_list(devices, 1);
// 退出 libusb
libusb_exit(ctx);
return result;
}
权限配置:
"requestPermissions":[ { "name": "ohos.permission.ACCESS_EXTENSIONAL_DEVICE_DRIVER" } ]
更多关于HarmonyOS 鸿蒙Next中libusb移植总结的实战教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next中移植libusb需关注以下几点:
- 使用HDF驱动框架替代传统Linux USB驱动交互
- 适配鸿蒙USB API接口,重点关注UsbClient、UsbPipe等核心类
- 修改libusb上下文初始化流程,替换udev相关代码为鸿蒙设备枚举方式
- 重新实现异步I/O机制,利用鸿蒙事件通知机制替代epoll
- 处理权限问题,需在config.json中声明ohos.permission.USB权限
移植后的libusb可支持标准USB设备操作,但需注意鸿蒙USB主机模式的限制。