From 70682ad13538d49b282d15cef181ecbc9bb1d3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cwangyipeng=E2=80=9D?= Date: Wed, 23 Nov 2022 15:26:26 +0800 Subject: [PATCH] fix:usb service northbound usage document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “wangyipeng” --- .../subsystems/subsys-usbservice-overview.md | 293 +++++++++++++++++- 1 file changed, 284 insertions(+), 9 deletions(-) diff --git a/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md b/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md index 6e89b406d5..d3bf8b07e6 100644 --- a/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md @@ -1,23 +1,51 @@ -# USB服务概述 - +# USB服务 ## 概述 +### 功能简介 + USB设备分为Host设备(主机设备)和Device设备(从设备)。用户可通过Port Service来根据实际业务把运行OpenHarmony的设备切换为Host设备或者Device设备。目前在Host模式下,支持获取USB设备列表,USB设备权限管理,控制传输、批量传输的同异步数据传输等,在Device模式下,支持HDC(调试)、ACM(串口)、ECM(网口)等功能的切换。 +### 基本概念 + +- USB服务 + + USB服务是应用访问底层的一种设备抽象概念。开发者根据提供的USB API,可以获取设备列表、控制设备访问权限、以及与连接的设备进行数据传输、控制命令传输等。 + +- USB API + + 基于USB Service服务,使用NAPI技术,向上提供JS接口。提供USB的基础API,主要包含查询USB设备的列表、设备插拔通知、USB HOST/DEVICE 功能切换、批量数据传输、控制命令传输、USB设备打开的权限控制及USB device模式下的function功能切换等。 + +- USB Service + + 使用C++代码实现,包含Host、Device、Port、Right四个模块。基于HDI接口,主要实现USB设备列表管理、Function 管理、Port管理、USB设备权限管理等功能。主要实现HAL层数据接收、解析、分发,前后台的策略管控,对该设备USB的管理,USB权限管控等。 + +- USB HAL + + 使用C代码实现,基于Host DDK(Driver Develop Kit)和Device DDK,封装了对USB设备的基本操作,向上提供C++接口,同时通过HDF框架接收内核上报的信息。 + +### 运作机制 + +USB服务系统包含USB API、USB Service、USB HAL。 + **图1** USB服务架构图 ![zh-cn_image_0000001267088285](figures/zh-cn_image_0000001267088285.png) -- USB API:基于USB Service服务,使用NAPI技术,向上提供JS接口。 +- USB API:提供USB的基础API,主要包含查询USB设备列表、批量数据传输、控制命令传输、权限控制等。 + +- USB Service:主要实现HAL层数据的接收、解析、分发,前后台的策略管控以及对设备的管理等。 -- USB Service:使用C++代码实现,包含Host、Device、Port三个模块。基于HDI接口,主要实现USB设备列表管理、Function 管理、Port管理、USB设备权限管理等功能。 +- USB HAL层:提供给用户态可直接调用的驱动能力接口。 -- USB HAL:使用C代码实现,基于Host DDK(Driver Develop Kit)和Device DDK,封装了对USB设备的基本操作,向上提供C++接口,同时通过HDF框架接收内核上报的信息。 +## 使用指导 +### 场景介绍 -## 接口说明 +Host模式下,可以获取到已经连接的设备列表,并根据需要打开和关闭设备、控制设备权限、进行数据传输等。 -- Host部分 +### 接口说明 + + **表1** Host部分 | 接口名称 | 功能描述 | | ------------------------------------------------------------ | ------------------------------------------------------------ | @@ -45,7 +73,7 @@ USB设备分为Host设备(主机设备)和Device设备(从设备)。用 | int32_t BulkWrite(USBDevicePipe &pip, const USBEndpoint &endpoint, sptr &ashmem); | 批量传输异步写 | | int32_t BulkCancel(USBDevicePipe &pip, const USBEndpoint &endpoint); | 批量传输异步取消接口,用于取消当前接口的异步批量读写操作 | -- Device部分 + **表2** Device部分 | 接口名称 | 功能描述 | | -------------------------------------------------- | ------------------------------------------------------ | @@ -54,10 +82,257 @@ USB设备分为Host设备(主机设备)和Device设备(从设备)。用 | int32_t UsbFunctionsFromString(std::string funcs); | 将给定的功能列表描述字符串转换为功能列表的数字组合掩码 | | std::string UsbFunctionsToString(int32_t funcs); | 将给定的功能列表的数字组合掩码转换为功能列表描述字符串 | -- Port部分 + **表3** Port部分 | 接口名称 | 功能描述 | | ------------------------------------------------------------ | -------------------------------------------------------- | | int32_t GetSupportedModes(int32_t portId, int32_t &supportedModes); | 获取指定的端口支持的模式列表的组合掩码 | | int32_t SetPortRole(int32_t portId, int32_t powerRole, int32_t dataRole); | 设置指定的端口支持的角色模式,包含充电角色、数据传输角色 | | int32_t GetPorts(std::vector &usbPorts); | 获取物理USB端口描述信息列表 | + +### USB服务子系统使用步骤 + +以bulktransfer为例。 + +1. 获取usb service实例。 + + ```cpp + static OHOS::USB::UsbSrvClient &g_usbClient = OHOS::USB::UsbSrvClient::GetInstance(); + ``` + +2. 获取usb设备列表。 + + ```cpp + std::vector deviceList; + int32_t ret = g_usbClient.GetDevices(deviceList); + ``` + +3. 申请设备权限。 + + ```cpp + int32_t ret = g_usbClient.RequestRight(device.GetName()); + ``` + +4. 打开设备。 + + ```cpp + USBDevicePipe pip; + int32_t et = g_usbClient.OpenDevice(device, pip); + ``` + +5. 配置设备接口。 + + ```cpp + //interface为deviceList中device的interface。 + ret = g_usbClient.ClaimInterface(pip, interface, true); + ``` + +6. 数据传输。 + + ```cpp + // pipe为打开设备后的数据传输通道,endpoint为device中数据传输的端点,vdata是需要传输或读取的二进制数据块,timeout为传输超时时长。 + srvClient.BulkTransfer(pipe, endpoint, vdata, timeout); + ``` + +7. 关闭设备。 + + ```cpp + ret = g_usbClient.Close(pip); + ``` + +### USB服务子系统使用实例 + +```cpp +#include +#include +#include +#include +#include +#include +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iremote_object.h" +#include "iservice_registry.h" +#include "iusb_srv.h" +#include "string_ex.h" +#include "system_ability_definition.h" +#include "usb_common.h" +#include "usb_device.h" +#include "usb_errors.h" +#include "usb_request.h" +#include "usb_server_proxy.h" +#include "usb_srv_client.h" + +const int32_t REQUESTYPE = ((1 << 7) | (0 << 5) | (0 & 0x1f)); +const int32_t REQUESTCMD = 6; +const int32_t VALUE = (2 << 8) + 0; +const int32_t TIMEOUT = 5000; +const int32_t ITFCLASS = 10; +const int32_t PRAMATYPE = 2; +const int32_t BUFFERLENGTH = 21; + +void GetType(OHOS::USB::USBEndpoint &tep, OHOS::USB::USBEndpoint &outEp, bool &outEpFlg) +{ + if ((tep.GetType() == PRAMATYPE)) { + if (tep.GetDirection() == 0) { + outEp = tep; + outEpFlg = true; + } + } +} + +bool SelectEndpoint(OHOS::USB::USBConfig config, + std::vector interfaces, + OHOS::USB::UsbInterface &interface, + OHOS::USB::USBEndpoint &outEp, + bool &outEpFlg) +{ + for (int32_t i = 0; i < config.GetInterfaceCount(); ++i) { + OHOS::USB::UsbInterface tif = interfaces[i]; + std::vector mEndpoints = tif.GetEndpoints(); + for (int32_t j = 0; j < tif.GetEndpointCount(); ++j) { + OHOS::USB::USBEndpoint tep = mEndpoints[j]; + if ((tif.GetClass() == ITFCLASS) && (tif.GetSubClass() == 0) && (tif.GetProtocol() == PRAMATYPE)) { + GetType(tep, outEp, outEpFlg); + } + } + if (outEpFlg) { + interface = interfaces[i]; + return true; + } + std::cout << std::endl; + } + return false; +} + +int OpenDeviceTest(OHOS::USB::UsbSrvClient &Instran, OHOS::USB::UsbDevice device, OHOS::USB::USBDevicePipe &pip) +{ + int ret = Instran.RequestRight(device.GetName()); + std::cout << "device RequestRight ret = " << ret << std::endl; + if (0 != ret) { + std::cout << "device RequestRight failed = " << ret << std::endl; + } + ret = Instran.OpenDevice(device, pip); + return ret; +} + +int CtrTransferTest(OHOS::USB::UsbSrvClient &Instran, OHOS::USB::USBDevicePipe &pip) +{ + std::cout << "usb_device_test : << Control Transfer >> " << std::endl; + std::vector vData; + const OHOS::USB::UsbCtrlTransfer tctrl = {REQUESTYPE, REQUESTCMD, VALUE, 0, TIMEOUT}; + int ret = Instran.ControlTransfer(pip, tctrl, vData); + if (ret != 0) { + std::cout << "control message read failed width ret = " << ret << std::endl; + } else { + } + std::cout << "control message read success" << std::endl; + + return ret; +} + +int ClaimTest(OHOS::USB::UsbSrvClient &Instran, + OHOS::USB::USBDevicePipe &pip, + OHOS::USB::UsbInterface &interface, + bool interfaceFlg) +{ + if (interfaceFlg) { + std::cout << "ClaimInterface InterfaceInfo:" << interface.ToString() << std::endl; + int ret = Instran.ClaimInterface(pip, interface, true); + if (ret != 0) { + std::cout << "ClaimInterface failed width ret = " << ret << std::endl; + } else { + std::cout << "ClaimInterface success" << std::endl; + } + } + return 0; +} + +int BulkTransferTest(OHOS::USB::UsbSrvClient &Instran, + OHOS::USB::USBDevicePipe &pip, + OHOS::USB::USBEndpoint &outEp, + bool interfaceFlg, + bool outEpFlg) +{ + if (interfaceFlg) { + std::cout << "usb_device_test : << Bulk transfer start >> " << std::endl; + if (outEpFlg) { + uint8_t buffer[50] = "hello world 123456789"; + std::vector vData(buffer, buffer + BUFFERLENGTH); + int ret = Instran.BulkTransfer(pip, outEp, vData, TIMEOUT); + if (ret != 0) { + std::cout << "Bulk transfer write failed width ret = " << ret << std::endl; + } else { + std::cout << "Bulk transfer write success" << std::endl; + } + return ret; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + std::cout << "usb_device_test " << std::endl; + static OHOS::USB::UsbSrvClient &Instran = OHOS::USB::UsbSrvClient::GetInstance(); + // GetDevices + std::vector deviceList; + int32_t ret = Instran.GetDevices(deviceList); + if (ret != 0) { + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } + if (deviceList.empty()) { + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } + + OHOS::USB::UsbDevice device = deviceList[0]; + std::vector configs = device.GetConfigs(); + OHOS::USB::USBConfig config = configs[0]; + std::vector interfaces = config.GetInterfaces(); + OHOS::USB::UsbInterface interface; + OHOS::USB::USBEndpoint outEp; + bool interfaceFlg = false; + bool outEpFlg = false; + interfaceFlg = SelectEndpoint(config, interfaces, interface, outEp, outEpFlg); + + // OpenDevice + std::cout << "usb_device_test : << OpenDevice >> test begin -> " << std::endl; + OHOS::USB::USBDevicePipe pip; + ret = OpenDeviceTest(Instran, device, pip); + if (ret != 0) { + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } + + // ControlTransfer + CtrTransferTest(Instran, pip); + + // ClaimInterface + ClaimTest(Instran, pip, interface, interfaceFlg); + + // BulkTransferWrite + BulkTransferTest(Instran, pip, outEp, interfaceFlg, outEpFlg); + + // CloseDevice + std::cout << "usb_device_test : << Close Device >> " << std::endl; + ret = Instran.Close(pip); + if (ret == 0) { + std::cout << "Close device failed width ret = " << ret << std::endl; + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } else { + std::cout << "Close Device success" << std::endl; + } + return 0; +} +``` + +### 参考手册 + +[驱动子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E9%A9%B1%E5%8A%A8%E5%AD%90%E7%B3%BB%E7%BB%9F.md) + +[drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral/blob/master/README_zh.md) + +[drivers\_framework](https://gitee.com/openharmony/drivers_framework/blob/master/README_zh.md) + +[drivers\_adapter](https://gitee.com/openharmony/drivers_adapter/blob/master/README_zh.md) + +[drivers\_adapter\_khdf\_linux](https://gitee.com/openharmony/drivers_adapter_khdf_linux/blob/master/README_zh.md) \ No newline at end of file -- GitLab