鸿蒙next教程:扩展外设驱动开发(开发适用USB协议的设备驱动)_harmonyosnext 打印驱动开发
往期鸿蒙全套实战文章必看:(附带鸿蒙全栈学习资料)
-
鸿蒙开发核心知识点,看这篇文章就够了
-
最新版!鸿蒙HarmonyOS Next应用开发实战学习路线
-
鸿蒙HarmonyOS NEXT开发技术最全学习路线指南
-
鸿蒙应用开发实战项目,看这一篇文章就够了(部分项目附源码)
开发适用USB协议的设备驱动
简介
USB DDK(USB Driver Develop Kit)是为开发者提供的USB驱动程序开发套件,支持开发者基于用户态,在应用层开发USB设备驱动。提供了一系列主机侧访问设备的接口,包括主机侧打开和关闭接口、管道同步异步读写通信、控制传输、中断传输等。
凡是采用USB总线,通过USB协议传输数据的设备都可以使用USB DDK开发设备驱动。特别是内核标准驱动不支持的扩展外设,可以通过USB DDK开发的扩展外设驱动应用实现其独特的设备能力。
基本概念
在进行USB DDK开发前,开发者应了解以下基本概念:
-
USB
USB(Universal Serial Bus,通用串行总线)是一种广泛使用的接口技术,用于连接计算机与各种外部设备,如键盘、鼠标、打印机、存储设备、智能手机等。USB 的设计目标是提供一种标准化、高效且易于使用的连接方式,以替代传统的串行和并行接口。
-
DDK
DDK(Driver Develop Kit)是HarmonyOS基于扩展外设框架,为开发者提供的驱动应用开发的工具包,可针对非标USB串口设备,开发对应的驱动。
实现原理
非标外设应用通过扩展外设管理服务获取USB设备的ID,通过RPC将ID和要操作的动作下发给USB驱动应用,USB驱动应用通过调用USB DDK接口可获取设备描述符,配置描述符,以及发送控制传输,中断传输等请求,DDK接口使用HDI服务将指令下发至内核驱动,内核驱动使用指令与设备通信。
图1 USB DDK调用原理
约束与限制
-
USB DDK开放API支持USB接口非标外设扩展驱动开发场景。
-
USB DDK开放API仅允许DriverExtensionAbility生命周期内使用。
-
使用USB DDK开放API需要在module.json5中声明匹配的ACL权限,例如ohos.permission.ACCESS_DDK_USB。
环境搭建
请参考环境准备完成开发前的准备工作。
开发指导
接口说明
详细的接口说明请参考USB DDK。
开发步骤
以下步骤描述了如何使用 USB DDK开发USB驱动:
添加动态链接库
CMakeLists.txt中添加以下lib。
libusb_ndk.z.so
头文件
#include #include
-
获取设备描述符。
使用 usb_ddk_api.h 的 OH_Usb_Init 接口初始化DDK,并使用 OH_Usb_GetDeviceDescriptor获取到设备描述符。
// 初始化USB DDKOH_Usb_Init();struct UsbDeviceDescriptor devDesc;uint64_t deviceId = 0;// 获取设备描述符OH_Usb_GetDeviceDescriptor(deviceId, &devDesc);
-
获取配置描述符及声明接口。
使用 usb_ddk_api.h 的 OH_Usb_GetConfigDescriptor 接口获取配置描述符 config,并使用 OH_Usb_ClaimInterface 声明\"认领\"接口。
struct UsbDdkConfigDescriptor *config = nullptr;// 获取配置描述符OH_Usb_GetConfigDescriptor(deviceId, 1, &config);// 根据配置描述符,找到所需要通信的interfaceIndexuint8_t interfaceIndex = 0;// 声明接口uint64_t interfaceHandle = 0;OH_Usb_ClaimInterface(deviceId, interfaceIndex, &interfaceHandle);// 释放配置描述符OH_Usb_FreeConfigDescriptor(config);
-
获取当前激活接口的备用设置及激活备用设置。
使用 usb_ddk_api.h 的 OH_Usb_GetCurrentInterfaceSetting 获取备用设置,并使用 OH_Usb_SelectInterfaceSetting 激活备用设置。
uint8_t settingIndex = 0;// 接口获取备用设置OH_Usb_GetCurrentInterfaceSetting(interfaceHandle, &settingIndex);// 激活备用设置OH_Usb_SelectInterfaceSetting(interfaceHandle, &settingIndex);
-
发送控制读请求、发送控制写请求。
使用 usb_ddk_api.h 的OH_Usb_SendControlReadRequest发送控制读请求,或者使用OH_Usb_SendControlWriteRequest发送控制写请求。
// 超时时间,设置为1s;uint32_t timeout = 1000;struct UsbControlRequestSetup setupRead;setupRead.bmRequestType = 0x80;setupRead.bRequest = 0x08;setupRead.wValue = 0;setupRead.wIndex = 0;setupRead.wLength = 0x01;uint8_t dataRead[256] = {0};uint32_t dataReadLen = 256;// 发送控制读请求OH_Usb_SendControlReadRequest(interfaceHandle, &setupRead, timeout, dataRead, &dataReadLen);struct UsbControlRequestSetup setupWrite;setupWrite.bmRequestType = 0;setupWrite.bRequest = 0x09;setupWrite.wValue = 1;setupWrite.wIndex = 0;setupWrite.wLength = 0;uint8_t dataWrite[256] = {0};uint32_t dataWriteLen = 256;// 发送控制写请求OH_Usb_SendControlWriteRequest(interfaceHandle, &setupWrite, timeout, dataWrite, &dataWriteLen);
-
创建内存映射缓冲区及发送请求。
使用 usb_ddk_api.h 的OH_Usb_CreateDeviceMemMap接口创建内存映射缓冲区devMmap,并使用OH_Usb_SendPipeRequest发送请求。
struct UsbDeviceMemMap *devMmap = nullptr;// 创建用于存放数据的缓冲区size_t bufferLen = 10;OH_Usb_CreateDeviceMemMap(deviceId, bufferLen, &devMmap);struct UsbRequestPipe pipe;pipe.interfaceHandle = interfaceHandle;// 根据配置描述符找到所要通信的端点pipe.endpoint = 128;pipe.timeout = UINT32_MAX;// 发送请求OH_Usb_SendPipeRequest(&pipe, devMmap);
-
释放资源。
在所有请求处理完毕,程序退出前,使用 usb_ddk_api.h 的 OH_Usb_DestroyDeviceMemMap 接口销毁缓冲区。使用OH_Usb_ReleaseInterface释放接口。使用OH_Usb_Release释放USB DDK。
// 销毁缓冲区OH_Usb_DestroyDeviceMemMap(devMmap);// 释放接口OH_Usb_ReleaseInterface(interfaceHandle);// 释放USB DDKOH_Usb_Release();
-
(独立步骤,可选)获取可识别的USB设备列表。
驱动拉起后调用OH_Usb_GetDevices接口获取驱动配置信息中匹配vid(vid是设备厂商的vendor id,在驱动应用里面配置,表示驱动适配哪些设备,查询到的设备ID都需要通过vid进行过滤)的设备ID,以供后续应用开发使用。
OH_Usb_Init();constexpr size_t MAX_USB_DEVICE_NUM = 128;struct Usb_DeviceArray deviceArray;deviceArray.deviceIds = new uint64_t[MAX_USB_DEVICE_NUM];// 获取设备列表OH_Usb_GetDevices(&deviceArray);