1# 外设驱动HDI接口定义 2 3## 简介 4 5该仓库用于管理各模块HDI(Hardware Device Interface)接口定义,接口定义使用IDL语言描述并以`·idl`文件形式保存。 6 7 8**图 1** HDI原理图 9 10 11 12使用IDL语法描述HDI接口并保存为`.idl`文件,`.idl`文件在编译过程中转换为C/C++语言的函数接口声明、客户端与服务端IPC相关过程代码,开发者只需要基于生成的`ifoo.h`函数接口实现具体服务功能即可。代码生成与编译功能已经集成在`//drivers/hdf_core/adapter/uhdf2/hdi.gni`编译模板,基于该编译模板编写`idl`文件的`BUILD.gn`就可以简单的生成客户端、服务端代码并编译为共享库。 13 14## 目录 15 16``` 17├── README.en.md 18├── README.md 19├── sensor #sensor HDI 接口定义 20│ └── v1_0 #sensor HDI 接口 v1.0版本定义 21│ ├── BUILD.gn #sensor idl文件编译脚本 22│ ├── ISensorCallback.idl #sensor callback 接口定义idl文件 23│ ├── ISensorInterface.idl #sensor interface 接口定义idl文件 24│ └── SensorTypes.idl #sensor 数据类型定义idl文件 25├── audio #audio HDI 接口定义 26│ └── ... 27├── camera #camera HDI接口定义 28├── codec #codec HDI接口定义 29├── display #display HDI接口定义 30├── face_auth #faceauth HDI接口定义 31├── format #format HDI接口定义 32├── input #input HDI接口定义 33├── misc #misc HDI接口定义 34├── pinauth #pinauth HDI接口定义 35├── usb #usb HDI接口定义 36├── fingerprint_auth #fingerprintauth HDI接口定义 37└── wlan #wlan HDI接口定义 38``` 39 40## 使用说明 41 421. 使用IDL语法编写 `.idl` 文件 43 44 - 参考上节目录结构创建对应模块/版本接口目录,初始版本定义为`v1_0`,如 `drivers/interface/foo/v1.0/` 45 46 - 定义接口 `IFoo.idl` 47 ``` 48 package ohos.hdi.foo.v1_0; 49 50 import ohos.hdi.foo.v1_0.IFooCallback; 51 import ohos.hdi.foo.v1_0.MyTypes; 52 53 interface IFoo { 54 Ping([in] String sendMsg, [out] String recvMsg); 55 56 GetData([out] struct FooInfo info); 57 58 SendCallbackObj([in] IFooCallback cbObj); 59 } 60 ``` 61 - 如果`interface`中用到了自定义数据类型,将自定义类型定义到`MyTypes.idl` 62 ``` 63 package ohos.hdi.foo.v1_0; 64 65 enum FooType { 66 FOO_TYPE_ONE = 1, 67 FOO_TYPE_TWO, 68 }; 69 70 struct FooInfo { 71 unsigned int id; 72 String name; 73 enum FooType type; 74 }; 75 ``` 76 - 如果需要从服务端回调,可以定义`callback`接口类`IFooCallback.idl` 77 ``` 78 package ohos.hdi.foo.v1_0; 79 80 [callback] interface IFooCallback { 81 PushData([in] String message); 82 } 83 ``` 84 851. 编写 `idl`文件的`BUILD.gn` 86 - 在上述`drivers/interface/foo/v1.0/`目录中添加`BUILD.gn`文件,内容参考如下: 87 ``` 88 import("//drivers/hdf_core/adapter/uhdf2/hdi.gni") # 编译idl必须要导入的模板 89 hdi("foo") { # 目标名称,会生成两个so,分别对应 libfoo_client_v1.0.z.so 和 libfoo_stub_v1.0.z.so 90 package = "ohos.hdi.foo.v1_0" # 包名,必须与idl路径匹配 91 module_name = "foo" # module_name控制dirver文件中驱动描 述符(struct HdfDriverEntry)的moduleName 92 sources = [ # 参与编译的idl文件 93 "IFoo.idl", # 接口idl 94 "IFooCallback.idl", # 用于回调的idl 95 "MyTypes.idl", # 自定义类型idl 96 ] 97 language = "cpp" # 控制idl生成c或c++代码 可选择`c`或`cpp` 98 } 99 ``` 100 1012. 实现 HDI 服务 102 103 在上述步骤中idl编译后将在out目录`out/[product_name]/gen/drivers/interfaces/foo/v1_0`生成中间代码。 104 105 - 实现HDI服务接口 106 107 基于工具自动生成的`foo_interface_service.h`,实现其中的服务接口,并将相关源码编译为FooService.z.so。 108 109 实现服务业务接口: 110 ``` 111 namespace OHOS { 112 namespace HDI { 113 namespace Foo { 114 namespace V1_0 { 115 116 class FooService : public IFoo { //继承接口类,并重写接口 117 public: 118 virtual ~FooService() {} 119 120 int32_t Ping(const std::string& sendMsg, std::string& recvMsg) override; 121 int32_t FooService::GetData(FooInfo& info) override; 122 int32_t FooService::SendCallbackObj(const sptr<IFooCallback>& cbObj) override; 123 }; 124 125 } // namespace V1_0 126 } // namespace Foo 127 } // namespace Hdi 128 } // namespace OHOS 129 ``` 130 131 - 实现驱动入口 132 133 HDI服务发布是基于用户态HDF驱动框架,所以需要实现一个驱动入口。驱动实现代码参考已经在out目录中生成,如`out/gen/xxx/foo_interface_driver.cpp`,可以根据业务需要直接使用该文件或参考该文件按业务需要重新实现。 134 然后将驱动入口源码编译为`libfoo_driver.z.so`(该名称无强制规定,与hcs配置中配套即可)。 135 1363. 发布服务 137 138 在产品hcs配置中声明HDI服务,以标准系统Hi3516DV300单板为例,HDF设备配置路径为`vendor/hisilicon/Hi3516DV300/hdf_config/uhdf/device_info.hcs`,在其中新增以下配置: 139 ``` 140 fooHost :: host { 141 hostName = "fooHost"; 142 priority = 50; 143 fooDevice :: device { 144 device0 :: deviceNode { 145 policy = 2; 146 priority = 100; 147 preload = 2; 148 moduleName = "libfoo_driver.z.so"; 149 serviceName = "foo_service"; 150 } 151 } 152 } 153 ``` 154 1554. 调用HDI服务 156 157 - 客户端在BUILD.gn中增加依赖: 158 `//drivers/interface/foo/v1.0:libfoo_proxy_1.0"` 159 160 - 在代码中调用HDI接口(以CPP为例) 161 ``` 162 #include <v1_0/ifoo_interface.h> 163 164 int WorkFunc(void) { 165 sptr<IFoo> foo = OHOS::HDI::Foo::V1_0::Foo::Get(); // 使用Foo对象的内置静态方法获取该服务客户端实例 166 if (foo == nullptr) { 167 // hdi service not exist, handle error 168 } 169 170 foo->Bar(); // do interface call 171 } 172 ``` 173 如果服务存在多实例可以通过指定实例名称的方法获取对应实例`Hdi::Foo::V1_0::Foo::GetInstance(const std::string& serviceName)`; 174 175## 约定 176 1771. idl 文件命名规则 178 179 - idl 文件以大驼峰命名,与接口名称保持一致,一般以字母‘I’开头。 180 - 接口描述文件以`.idl`作为后缀。 181 1821. 接口命名规则 183 184 | 类型 | 命名风格 | 185 | ----- | ------- | 186 | 类、结构体、枚举、联合体等类型名,包名 | 大驼峰 | 187 | 方法 | 大驼峰 | 188 | 函数参数,类、结构体和联合体中的成员变量 | 小驼峰 | 189 | 宏,常量(const),枚举值 | 全大写,下划线分割 | 190 1911. 接口版本号命名规则 192 193 HDI接口版本号使用语义化版本号定义,即[major].[minor]。 194 - major版本号不同表示接口间不兼容; 195 - minor版本不同但是major版本号相同表示接口相互兼容,这种情况下不允许修改以前接口的接口名称、参数类型/个数、返回值类型/个数。 196 197## 相关仓 198 199[驱动子系统](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) 200 201 202[drivers\_adapter](https://gitee.com/openharmony/drivers_adapter/blob/master/README_zh.md) 203 204 205[drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral/blob/master/README_zh.md) 206