• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# OpenHarmony HDI Design Specifications
2
3## Overview
4
5Hardware device interface (HDI) provides a set of interfaces that function as a bridge between drivers and system services for data transmission. They have a direct impact on system efficiency, stability, compatibility, and reliability, as well as data accuracy and integrity. This document aims to standardize the design and development of OpenHarmony HDI interfaces, thereby ensuring consistent styles and complete functionalities for the interfaces.
6This document is developed by the [driver SIG](https://gitee.com/openharmony/community/blob/master/sig/sig_driver/sig_driver.md) and approved by the [PMC](https://gitee.com/link?target=https%3A%2F%2Fwww.openharmony.cn%2Fcommunity%2Fpmc%2F). Any revision to this document must be reviewed by the driver SIG and approved by the PMC.
7
8**Acronyms**
9
10| Acronym | Full Spelling                           |
11| --- | ------------------------------ |
12| HDI | Hardware Device Interface      |
13| IDL | Interface Description Language |
14
15**Conventions**
16
17**Rule**: a convention that must be complied with
18
19**Rec**: a convention that should be considered
20
21**Note**: an explanation to a rule or rec
22
23**Change History**
24| Version | Change Description              |
25| ---  | --------------------- |
26| v1.0 Beta | This issue is the initial version.              |
27| v1.0  | This issue is the official version.              |
28
29
30## Scope and Definition
31
32![](https://gitee.com/openharmony/docs/raw/master/en/design/figures/API-Category.png)
33
34Located between the system service layer and the device driver layer, HDI provides unified device function abstract interfaces for device developers. It shields the differences of devices from system services.
35
36## General Rules
37
38### Version Control
39
40The HDI version number must be in the format of `major.minor`, where `major` must be an integer increased in ascending order and `minor` is a one-digit integer.
41
42- A change in `major` indicates architecture adjustment or interface definition that is not backward compatible.
43
44- A change in `minor` indicates enhanced or extended interface definitions that are backward compatible.
45
46When `major` changes, `minor` is reset to `0`.
47
48[Example]
49
50For released vibrator interfaces:
51
52```cpp
53package ohos.hdi.vibrator.v1_0;
54interface IVibrator {
55   ...
56   SetModulationParameter([in] unsigned int vibrationPeriod, [in] int intensity, [in] int frequency);
57   ...
58}
59```
60
61If the update to the existing interfaces does not affect version compatibility, for example, adding a function, adding an enum definition, or changing a variable name, change only `minor`, for example, to `ohos.hdi.vibrator.v1_1`, as follows:
62
63```cpp
64package ohos.hdi.vibrator.v1_1;
65interface IVibrator {
66   ...
67   SetModulationParameter([in] unsigned int vibrationPeriod, [in] int intensity, [in] int freq);
68   ...
69}
70```
71
72If the original interface is renamed or the variable list is modified, change `major`, for example, to `ohos.hdi.vibrator.v2_0`, as follows:
73
74```cpp
75package ohos.hdi.vibrator.v2_0;
76interface IVibrator {
77   ...
78   SetModulationParameter([in] unsigned int vibrationPeriod, [in] int intensity, [in] int frequency, [int] time);
79   ...
80}
81```
82
83### Review and Control
84
85HDI interfaces are provided to implement upper-layer system service requirements and perform hardware operations (such as initialization). New and updated interfaces must be fully reviewed and strictly controlled. Only interfaces that meet universal requirements can be added.
86
87Table 1 Interface review and control roles
88
89| **Role**   | **Responsibility**                                   |
90| ----------- | ------------------------------------------------ |
91| Contributor | Write HDI code and submit the code and design documents for review.                   |
92| Committer   | Review the HDI code, and submit the code to the domain SIG for further review.                           |
93| Domain SIG    | Review the new or updated HDI code.|
94| Driver SIG  | Review the new or updated HDI code.                                 |
95| PMC         | Revise and publish this design specifications.                 |
96
97### Release
98
99- HDI review process
100
101    ![](figures/HDI-Review-Process.png)
102
103    The main process is as follows:
104
105    1. The contributor commits code and initiates a review. In addition to the code of new or updated HDI interfaces, the contributor must provide information about the HDI requirement source, usage scenario, permission design, and privacy protection design. For details, see "Review application composites" below. To increase the review efficiency, the contributor can email the design documents to the committer, domain SIG, and driver SIG before submitting the review application.
106    2. The committer reviews the code and HDI interfaces.
107    3. The domain SIG reviews the new or updated HDI interfaces.
108    4. The driver SIG reviews and approves the new or updated HDI interfaces.
109    5. The review is complete, and the code is merged.
110
111- Review application composites
112
113    After the HDI design is complete, the domain SIG must organize an effective review and provide the following documents before HDI release:
114
115    - Complete and reasonable test cases
116
117    - **HDI version differences, with a clear addition or change scope**
118
119    - Complete interface context, which must be provided in the design document to specify when and how to use each interface
120
121    - Resource status transition diagram in the design document for resource-oriented interfaces
122
123    - Compliance with the HDI design constraints proposed in this document
124
125- Requirements
126
127    1. Change `major` for any release that is incompatible with earlier versions.
128
129    2. Change `minor` for any interface released for function extension.
130
131    3. To deprecate any released interface:
132
133        - The `deprecated` flag must be provided.
134
135        - The deprecated interfaces must be retained in at least four OpenHarmony HDI versions.
136
137## HDI Design Constraints
138
139### Consistency
140
141#### [Rule] Use consistent nouns for terms.
142
143Multiple nouns with similar semantic meanings are not allowed to represent the same service object. Similarly, to avoid confusion, it is not allowed to use the same noun or linguistically close nouns for different service objects.
144
145#### [Rule] Keep the parameter sequence consistent.
146
147The sequence of a parameter or parameter group in multiple interfaces must be the same.
148
149For object-oriented C programming, place the interface object as the first parameter by convention.
150
151#### [Rule] Keep the memory ownership consistent.
152
153If the memory (storage data) passed through the input parameter (in) or output parameter (out) is allocated by the caller, the memory must be released by the caller. If the memory is allocated by the callee, it must be released by the callee. Regardless of whether data is passed from a service to a driver or received from a driver, the ownership of the data should not be changed, which must always be the memory allocator.
154
155[Example]
156
157```cpp
158int (*OpenLayer)(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId);
159```
160
161When **OpenLayer** is called, the graphics layer data memory is allocated based on the input parameter **layerInfo**, and a layer ID is returned.
162
163```cpp
164int (*CloseLayer)(uint32_t devId, uint32_t layerId);
165```
166
167A **CloseLayer** interface must be provided to release the graphics layer data memory when the caller finishes the operation.
168
169#### [Rule] Provide a specific return value for every synchronous interface.
170
171When defining a synchronous interface, you must define the return value and provide necessary invocation status information to specify whether the invocation is successful. If the invocation fails, specify the cause of the failure. You can define a return value based on the actual error cause.
172
173[Exceptions]
174
175If an interface is unidirectional, which means that a value can be returned without waiting for the interface to be executed, use the keyword `one way` in the comment. Example:
176
177```cpp
178/* one way */
179void WriteReady();
180```
181
182### Naming
183
184#### [Rule] Name an interface in the format of "I" + "*interface name*".
185Interface names must be concise, easy to understand, and accurate. Avoid redundant and misleading words, or rare abbreviations.
186
187[Example]
188```
189    /* Good */
190    interface IBattery {
191        ...
192    }
193
194   /* Bad: The Interface suffix is redundant. */
195    interface IBatteryInterface {
196        ...
197    }
198```
199#### [Rule] Name the HDI package in the format of "package ohos.hdi.[interface_name].v[major_version]_[minor_version]".
200[Example]
201```
202    /* Good */
203    package ohos.hdi.battery.v1_0;
204    interface IBattery {
205        ...
206    }
207
208   /* Bad: The hdi namespace and version information are missing. */
209   package ohos.battery;
210    interface IBattery {
211        ...
212    }
213```
214#### [Rule] Name classes, structs, functions, and parameters in camel case.
215**Camel case style**
216Camel case is the practice of writing words without spaces. It indicates the separation of words with a single capitalized letter, and the first word starts with either case, bringing about **UpperCamelCase** and **lowerCamelCase**.
217
218
219| Type                                      | Style     |
220| ---------------------------------------- | --------- |
221| Interface types, functions, struct types, enum types, and union types      | UpperCamelCase      |
222| Parameters, and member variables in a struct or union| lowerCamelCase      |
223| Constants and enums                 | All uppercase letters, separated by underscores (_)|
224
225#### [Rule] Use the interface class name as the interface file name and `.idl` as the file name extension.
226- An independent interface file must be provided for every interface class, and the file name must be the same as that of the interface class (UpperCamelCase) and end with `.idl`.
227- The description file of the type definition must be named `Types.idl` or `ExampleTypes.idl`.
228
229[Example]
230
231```
232    package ohos.hdi.battery.v1_0;
233    interface IBattery {
234        ...
235    }
236```
237   The interface description file must be named `IBattery.idl`.
238
239### Ease to Use
240
241#### [Rule] Follow the single responsibility principle.
242
243The functionalities of each interface must be stable and clear, and the trigger source of interface changes must be unique.
244
245[Example]
246
247When the device status consists of the power status and port status, use two interfaces rather than one.
248
249**Correct Example**
250
251```cpp
252int UpdatePowerState(int_t deviceId, int status); // This interface is used to update the power status of the device.
253
254int UpdatePortStatus(int deviceId, int status); // This interface is used to update the port status of the device.
255```
256
257**Incorrect Example**
258
259```cpp
260int UpdateDeviceStatus(int deviceId, int powerStatus, int portStatus);
261```
262
263#### [Rule] Consider cohesion during interface parameter design.
264
265When defining an interface parameter, consider whether to pass the parameter separately or encapsulate the parameter in a struct based on the following factors:
266
2671. Is there a meaningful encapsulation boundary?
268
269    If there is obvious cohesion or association between parameters, you can encapsulate these parameters in a struct.
270
2712. Is there any other use of this struct if structured parameters are used?
272
273    If no, pass the parameter separately.
274
2753. Does a parameter group occur in multiple interfaces?
276
277    If yes, you can pass these parameters as a struct. In this case, you also need to consider whether these parameter groups are cohesive.
278
2794. Is there a large number of optional parameters, or do they usually be assigned a default value?
280
281    If yes, you can use a struct to simplify the invocation.
282
283[Example]
284
285Audio sampling attributes include the sampling format, sampling frequency, and number of channels. These attributes are also sampling related and can be passed as a struct.
286
287```cpp
288struct AudioSampleAttributes
289{
290    enum AudioFormat format;
291    uint32_t sampleRate;
292    uint32_t channelCount;
293};
294```
295
296#### [Rule] Make interfaces of different device types independent from each other.
297
298Interfaces are managed by driver type, such as `Camera`, `Input`, `Display`, `Audio`, `Sensor`, and `Storage`. Interfaces of different device types should not depend on each other. It is recommended that common capabilities that may be used by more than two types of driver modules be abstracted as common interfaces and archived to the common interface capability library for management.
299
300[Exceptions]
301
302There is no restriction on the interfaces that provide common capabilities. For example, the definition of primitive types and the declaration of interfaces can be referenced by all interfaces.
303
304### Privacy Protection
305
306### [Rule] Consider privacy security.
307
308System services can access data such as device information and identifiers through drivers. Certain information, such as device names, serial numbers, and device addresses, is sensitive data defined in privacy protection specifications. During HDI design, pay attention to the use of these fields and review them carefully and thoroughly to ensure that the interfaces will never expose sensitive information.
309
310[Example]
311
312`Bluetooth` addresses are mainly used in device discovery and connection scenarios. When a device is discoverable, the `Bluetooth` address could be used for personal tracking.
313
314The major purpose of obtaining a `Bluetooth` address is to uniquely identify a device. Therefore, you can convert the `Bluetooth` address into a unique identifier for invocation or restrict the application scope of this interface.
315
316### Permission Control
317
318#### [Rule] Minimize the interface permissions.
319
320All behaviors across application sandboxes must be controlled by permissions. A specific permission can be granted only to applications that have legitimate service requirements.
321
322### Performance
323
324#### [Rule] Consider data transmission efficiency.
325
326Drivers have a large number of data transmission interfaces. Data transmission may involve inter-process communication (IPC), which increases system overheads or even trigger system scheduling. Therefore, you need to consider all situations when defining interfaces. For the data that must be transmitted between processes with low overhead and low latency, you can use the shared memory or message queue.
327
328[Example]
329
330Define a data transmission interface for a driver module as follows:
331
332```cpp
333// IPC is not involved (direct interface calling).
334int WriteData (...); // Define the data address pointer and data length as input parameters.
335
336/*
337 * IPC is involved.
338 *
339 * Define a shared memory or message queue object as the input parameter.
340 * In this way, data can be efficiently transmitted (since repetitive operations can be minimized).
341 */
342int PrepareWriteData(…);
343```
344
345#### [Rec] Consider the interface execution time.
346
347To improve IPC performance, you are advised to use asynchronous processing for time-consuming services on the server. If the client needs to wait for the result synchronously, you are advised to add a block on the client and use the asynchronous callback mode so that the IPC channel can be released in time.
348
349[Example]
350
351The `Camera` driver provides a device initialization interface, the execution of which takes more than 150 ms due to software and hardware reasons. If this interface uses synchronous mode, the camera HDI service IPC thread may be occupied for a long time, and other requests fail to be responded in time. It is more reasonable to design this interface as an asynchronous one. A callback can be used to return the initialization result to the client. If the client needs to wait for the return value before continuing other operations, it can block the process and wait for the callback result.
352
353#### [Rec] Minimize the number of new process entities.
354
355To reduce the system overhead, interfaces of the same type in the same subsystem must be deployed in the same process. Add processes only when they are necessary.
356
357### Power Consumption
358
359#### [Rule] Consider system power consumption.
360
361When the caller releases hardware resources, the corresponding driver module should release the wake lock so the system will not be prevented from sleeping.
362
363### Reliability
364
365#### [Rule] Mutual dependency is forbidden for the lifecycle of interface parameters.
366
367The lifecycle of interface parameters must be independent. Mutual dependency is prohibited. Pointer parameters should not point to the memory of other objects, for example, the serialized memory. This is because when the serialized memory is passed to the peer function, the memory block lifecycle disappears after the parameter is parsed, but the pointer may be passed between different functions, resulting in vulnerabilities such as Used After Free (UAF).
368
369[Example]
370
371Both `ReadUnpadBuffer` and `ReadCString` return a pointer variable that points to the internal memory of the serialized object. When the server callback is triggered, the serialized object used to pass the parameters is destroyed and the memory is free. If other processes on the server still use the pointers returned by the two interfaces, crash may occur due to the UAF.
372
373The correct practice is to copy the data to the memory managed by the service before using the data after the service response interface returns the data.
374
375#### [Rule] Consider reentrancy.
376
377Interfaces often need to support multiple clients, and a single client may have concurrent requests. Therefore, you must consider reentrancy during HDI design. To ensure correct processing of reentrant interfaces, use locks or semaphores to protect critical resources.
378
379[Example]
380
381A driver service provides resource request and release interfaces. When two clients request resources at the same time, if reentrancy is not considered for critical resources on the server, resources may be released in advance or cannot be released due to management data read/write competition. The correct practice is to lock critical resources.
382
383#### [Rec] Consider the transmission buffer capability.
384
385No flow control is posed on the amount of data sent in an interface or callback. However, if the data volume of an interface exceeds the maximum transmission buffer size, consider using a block until the resource is available.
386
387[Example]
388
389When memory application fails, you can use a semaphore to block the current thread until the memory is available.
390
391#### [Rule] Do not pass function pointers across address spaces.
392
393Virtual address space isolation is used between processes. Passing function pointers through IPC will cause access exceptions. Therefore, do not pass function pointers. To implement a callback function, use a callback object instead.
394
395[Example]
396
397The Wi-Fi module provides an interface to receive a callback triggered when the client accepts the server request. An incorrect practice is to write the function pointer implemented by the client to the serialized object, which causes a crash when the function pointer is called on the server.
398
399The correct practice is to design and implement the callback interface using a callback object, and pass the callback object to the server through the serialization interface, so the server can trigger the callback when needed.
400
401### Compatibility
402
403#### [Rule] Verify the version number before the client calls an interface.
404
405Due to the independent component update policy, the version number of an interface on the client may be different from that on the server. This requires the client to verify the version number on the server and use the matching version to call the interface on the server.
406
407[Example]
408
409Assume that the TP module provides interfaces of versions 1.0 and 1.1. The later version has new interfaces. The components on the client have updated to 1.1, and the server still uses 1.0. If the client directly calls an interface of 1.1 on the server, an error may occur. Instead, the client must use the service version query interface to check the server version. If the server version is 1.0, the client must use the interface of 1.0 to call the server.
410
411#### [Rule] Release HDI interfaces in .idl format.
412
413Currently, Unix-like drivers use virtual file system (VFS) interfaces to expose internal interfaces. The user mode and kernel mode communicate with each other using system calls. They are packed in different images, and two sets of interfaces are maintained separately. To ensure the consistency of the interface definition and parameter format between the two and consider the design objective of cross-kernel hardware driver foundation (HDF) deployment, release interfaces in .idl format and use a tool to generate interfaces of the target form. In addition, the user-mode caller is not allowed to operate the driver VFS interfaces through the file interface. This causes the framework to strongly depend on the kernel and violates the principle of depending on the interface instead of the implementation.
414
415Recommended practice: The driver provides interfaces in .idl format and encapsulates the access to the kernel device in the interface implementation.
416
417[Example]
418
419An input device provides query interfaces for attributes such as the device type and data precision. The input service should not directly access the VFS interface created by the kernel in open-ioctl mode. Instead, the input driver should provide an interface to abstract the input device as an object. Then the input service calls this interface to implement the required functionalities.
420
421### Documentation
422
423#### [Rule] Release HDI interfaces in .idl format.
424To ensure interface compatibility and consistency, release interfaces in .idl format. It is prohibited to directly release interfaces in C/C++ header files.
425
426
427#### [Rule] Provide an interface description during interface release.
428The interface description must contain the interface functionality, parameter value range, return values, and precautions. The description text must be placed above the interface description in the .idl file and released with the interface.
429
430[Example]
431
432```
433/**
434    * @brief Obtains the executor information.
435    *
436    * @param executorInfo Indicates the executor information. For details, see {@link ExecutorInfo}.
437    *
438    * @return Returns <b>0</b> if the operation is successful.
439    * @return Returns a non-zero value if the operation fails.
440    */
441GetExecutorInfo([out] struct ExecutorInfo executorInfo);
442```
443
444### Programming Languages
445
446To ensure data interworking between interfaces implemented in different programming languages, follow the restrictions below when using data types in the interface description.
447
448#### Constraints on using basic data types
449
450| IDL Data Type | C++ Data Type | C Data Type       | Data Length (Bytes)|
451| -------------- | ----------- | --------------- | ----------- |
452| void           | void        | void            | NA          |
453| boolean        | bool        | bool            | 1           |
454| byte           | int8_t      | int8_t          | 1           |
455| short          | int16_t     | int16_t         | 2           |
456| int            | int32_t     | int32_t         | 4           |
457| long           | int64_t     | int64_t         | 8           |
458| float          | float       | float           | 4           |
459| double         | double      | double          | 8           |
460| String         | std::string | char*, int size | NA          |
461| unsigned char  | uint8_t     | uint8_t         | 1           |
462| unsigned short | uint16_t    | uint16_t        | 2           |
463| unsigned int   | uint32_t    | uint32_t        | 4           |
464| unsigned long  | uint64_t    | uint64_t        | 8           |
465
466#### Constraints on Using Container Types
467
468| IDL Container Data Type| C++ Data Type     | C Data Type      |
469| ----------- | ------------ | ----------- |
470| List<T>     | std::list<T> | T*,int size |
471
472#### Constraints on Using Array Types
473
474| IDL Array Data Type | C++ Data Type       | C Data Type      |
475| --------- | -------------- | ----------- |
476| T[]       | std::vector<T> | T*,int size |
477
478#### Constraints on Using Custom Types
479
480| IDL Custom Data Type| C++ Data Type| C Data Type |
481| ------- | ------- | ------ |
482| struct  | struct  | struct |
483| enum    | enum    | enum   |
484