1e41f4b71Sopenharmony_ci# HDF Driver Coding Guide
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## About This Document
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci### Purpose
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciOpenHarmony aims to build an open, distributed OS framework for smart IoT devices in the full-scenario, full-connectivity, and full-intelligence era. It has the following technical features: hardware collaboration for resource sharing, one-time development for multi-device deployment, and a unified OS for flexible deployment.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe Hardware Driver Foundation (HDF) provides the following driver framework capabilities: driver loading, driver service management, and driver message mechanism. This unified driver architecture system is designed to provide a more precise and efficient development environment, where you can perform one-time driver development for multi-system deployment.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ciAs such, certain coding specifications are required for the OpenHarmony driver implemented based on the HDF. This document stipulates the specifications on the driver code, helping you improve code standardization and portability.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci## Coding Guide
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci### General Principles
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci#### [Rule] Use the capabilities provided by the HDF to implement drivers.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci[Description] The HDF supports driver loading, driver service management, and driver message mechanism. It provides the Operating System Abstraction Layer (OSAL) and Platform Abstraction Layer (PAL) to support cross-system and cross-platform driver deployment. It also provides capabilities such as driver model abstraction, common tools, and peripheral component framework. You should develop drivers based on these capabilities to ensure that the drivers can be deployed on various devices powered by OpenHarmony.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci#### [Rule] Follow this coding guide to develop drivers that can run in both the kernel space and user space.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci[Description] Kernel-mode drivers are different from user-mode drivers in essence. They apply to different use cases. You must follow this guide during service design and development and use the HDF OSAL and PAL to shield the differences, so as to ensure that the drivers can run in both the kernel space and user space.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci#### [Rec] Include the drivers/framework/include directory instead of a subdirectory in the build script.
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ci[Description] The **drivers/framework/include** directory is the root directory of the header file exposed by the HDF externally. This directory contains multiple subdirectories to represent different modules such as the core framework, OSAL, and PAL. When using a header file, you are advised to include the **drivers/framework/include** directory in the build script. This avoids repeated inclusion when the script is referenced in the code.
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci[Example]
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci```gn
32e41f4b71Sopenharmony_ciconfig("xxxx_private_config") {
33e41f4b71Sopenharmony_ci  include_dirs = [
34e41f4b71Sopenharmony_ci    "//drivers/framework/include",
35e41f4b71Sopenharmony_ci    "//drivers/framework/include/core", # Not recommended.
36e41f4b71Sopenharmony_ci  ]
37e41f4b71Sopenharmony_ci}
38e41f4b71Sopenharmony_ci```
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci```c
41e41f4b71Sopenharmony_ci#include <core/hdf_device_desc.h>
42e41f4b71Sopenharmony_ci#include <hdf_device_desc.h> // Not recommended.
43e41f4b71Sopenharmony_ci```
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci### HDF Core Framework
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci#### [Rule] Implement the Bind, Init, and Release methods based on the responsibility definitions in the HdfDriverEntry object.
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci[Description] The **HdfDriverEntry** object is the entry of an HDF driver. The **Bind**, **Init**, and **Release** methods have their own responsibilities. You must implement the corresponding functions based on the responsibilities.
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci```c
52e41f4b71Sopenharmony_cistruct HdfDriverEntry g_sampleDriverEntry = {
53e41f4b71Sopenharmony_ci    .moduleVersion = 1,
54e41f4b71Sopenharmony_ci    .moduleName = "sample_driver",
55e41f4b71Sopenharmony_ci    .Bind = SampleDriverBind, // Responsibility: Bind the service interface provided by the driver to the HDF.
56e41f4b71Sopenharmony_ci    .Init = SampleDriverInit, // Responsibility: Initialize the driver service.
57e41f4b71Sopenharmony_ci    .Release = SampleDriverRelease, // Responsibility: Release driver resources. It is invoked when an exception occurs.
58e41f4b71Sopenharmony_ci};
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ciHDF_INIT(g_sampleDriverEntry);
61e41f4b71Sopenharmony_ci```
62e41f4b71Sopenharmony_ci
63e41f4b71Sopenharmony_ci#### [Rule] The first member in the driver service structure must be of the IDeviceIoService type.
64e41f4b71Sopenharmony_ci
65e41f4b71Sopenharmony_ci[Description] The first member of the service interface defined by the driver must be of the **IDeviceIoService** type.
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ci[Example]
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ci```c
70e41f4b71Sopenharmony_cistruct ISampleDriverService {
71e41f4b71Sopenharmony_ci    struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type.
72e41f4b71Sopenharmony_ci    int32_t (*FunctionA)(void); // The first service interface of the driver.
73e41f4b71Sopenharmony_ci    int32_t (*FunctionB)(uint32_t inputCode); // The second service interface of the driver. More service interfaces can be added here.
74e41f4b71Sopenharmony_ci};
75e41f4b71Sopenharmony_ci```
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci[Example]
78e41f4b71Sopenharmony_ci
79e41f4b71Sopenharmony_ci```c
80e41f4b71Sopenharmony_cistruct ISampleDriverService {
81e41f4b71Sopenharmony_ci    struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type.
82e41f4b71Sopenharmony_ci    void *instance; // A service instance can be encapsulated here to provide service interfaces.
83e41f4b71Sopenharmony_ci};
84e41f4b71Sopenharmony_ci```
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci#### [Rule] All driver service interfaces must be bound using the Bind method of the HdfDriverEntry object. All service interfaces must be defined. They cannot be defined as null.
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci[Description] The service interfaces defined by the driver are exposed externally. If a service interface is not defined or is defined as null, exceptions may occur during external invocation.
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ci[Example]
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci```c
93e41f4b71Sopenharmony_ciint32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
94e41f4b71Sopenharmony_ci{
95e41f4b71Sopenharmony_ci    static struct ISampleDriverService sampleDriver = {
96e41f4b71Sopenharmony_ci        .FunctionA = SampleDriverServiceA,
97e41f4b71Sopenharmony_ci        .FunctionB = NULL, // The service interface cannot be defined as null.
98e41f4b71Sopenharmony_ci    };
99e41f4b71Sopenharmony_ci    // Bind ioService to the device object created by the HDF.
100e41f4b71Sopenharmony_ci    deviceObject->service = &sampleDriver.ioService;
101e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
102e41f4b71Sopenharmony_ci}
103e41f4b71Sopenharmony_ci```
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ci#### [Rec] Call the HdfDeviceSetClass interface in the Init method of the HdfDriverEntry object to define the driver type.
106e41f4b71Sopenharmony_ci
107e41f4b71Sopenharmony_ci[Description] Based on the driver type, you can classify the drivers of the current device and query the driver capabilities of the current device. For better driver management, you are advised to call **HdfDeviceSetClass** to set the driver type.
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ci[Example]
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ci```c
112e41f4b71Sopenharmony_ciint32_t SampleDriverInit(struct HdfDeviceObject *deviceObject)
113e41f4b71Sopenharmony_ci{
114e41f4b71Sopenharmony_ci    // Set the driver type to DISPLAY.
115e41f4b71Sopenharmony_ci    if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_DISPLAY)) {
116e41f4b71Sopenharmony_ci        HDF_LOGE("HdfDeviceSetClass failed");
117e41f4b71Sopenharmony_ci        return HDF_FAILURE;
118e41f4b71Sopenharmony_ci    }
119e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
120e41f4b71Sopenharmony_ci}
121e41f4b71Sopenharmony_ci```
122e41f4b71Sopenharmony_ci
123e41f4b71Sopenharmony_ci### HCS
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ciHDF Configuration Source (HCS) describes the configuration source code of the HDF in the form of key-value pairs. It decouples configuration code from driver code, making it easy for you to manage the driver configuration.
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ciThe driver configuration consists of the driver device description defined by the HDF and the private configuration of a driver.
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci**Driver Device Description**
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ciThe driver loading information required by the HDF comes from the driver device description. Therefore, you must add the driver device description to the **device_info.hcs** file defined by the HDF.
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci#### [Rule] Before configuring a driver, determine the hardware to which the driver belongs and the deployment mode, and plan the directories and files to be configured.
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci[Description] In the **vendor** directory of the OpenHarmony source code, plan the directories based on the chip vendor, development board, and configuration. The HDF driver configuration is stored in the **hdf\_config** directory. According to the hardware specifications, the **hdf\_config** directory stores kernel-mode configuration information or both kernel- and user-mode configuration information. You should determine the directory where the driver is to be configured based on the driver hardware and deployment mode.
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci[Example]
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci```bash
140e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus/hdf_config # Directory for storing the kernel-mode configuration file. There are no user-mode configuration files.
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf # Directory for storing the kernel-mode configuration file.
143e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/uhdf # Directory for storing the user-mode configuration file.
144e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/device_info/device_info.hcs # Device description file of the kernel-mode driver.
145e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/lcd/lcd_config.hcs # Private configuration file of the kernel-mode driver.
146e41f4b71Sopenharmony_ci```
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ci#### [Rule] Use existing configuration information and inherit existing configuration templates during driver configuration.
149e41f4b71Sopenharmony_ci
150e41f4b71Sopenharmony_ci[Description] The **host**, **device**, and **deviceNode** templates have been configured in the **device_info.hcs** file. When configuring a driver, make full use of the existing configuration information and inherit HCS features to minimize your configuration workload.
151e41f4b71Sopenharmony_ci
152e41f4b71Sopenharmony_ci[Example]
153e41f4b71Sopenharmony_ci
154e41f4b71Sopenharmony_ci```
155e41f4b71Sopenharmony_ciroot {
156e41f4b71Sopenharmony_ci    device_info {
157e41f4b71Sopenharmony_ci        match_attr = "hdf_manager";
158e41f4b71Sopenharmony_ci        template host { // host template
159e41f4b71Sopenharmony_ci            hostName = "";
160e41f4b71Sopenharmony_ci            priority = 100; // Host startup priority. The value ranges from 0 to 200. A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence cannot be ensured.
161e41f4b71Sopenharmony_ci            template device { // device template
162e41f4b71Sopenharmony_ci                template deviceNode { // deviceNode template
163e41f4b71Sopenharmony_ci                    policy = 0; // Policy for publishing drive services.
164e41f4b71Sopenharmony_ci                    priority = 100; // Driver startup priority. The value ranges from 0 to 200. A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the device loading sequence cannot be ensured.
165e41f4b71Sopenharmony_ci                    preload = 0; // The driver is loaded as required.
166e41f4b71Sopenharmony_ci                    permission = 0664; // Permission for the driver to create a device node.
167e41f4b71Sopenharmony_ci                    moduleName = "";
168e41f4b71Sopenharmony_ci                    serviceName = "";
169e41f4b71Sopenharmony_ci                    deviceMatchAttr = "";
170e41f4b71Sopenharmony_ci                }
171e41f4b71Sopenharmony_ci            }
172e41f4b71Sopenharmony_ci        }
173e41f4b71Sopenharmony_ci        // To use the default values in the template, the node fields can be not included.
174e41f4b71Sopenharmony_ci        sample_host :: host { // sample_host inherits the host template.
175e41f4b71Sopenharmony_ci            hostName = "host0"; // Host name. The host node is a container used to store a type of drivers.
176e41f4b71Sopenharmony_ci            device_sample :: device { // device_sample inherits the device template.
177e41f4b71Sopenharmony_ci                device0 :: deviceNode { // device0 inherits the deviceNode template.
178e41f4b71Sopenharmony_ci                    policy = 1; // Overwrite the policy in the template.
179e41f4b71Sopenharmony_ci                    moduleName = "sample_driver"; // Driver name. The value of this field must be the same as that of moduleName in the HdfDriverEntry structure.
180e41f4b71Sopenharmony_ci                    serviceName = "sample_service"; // Service name of the driver, which must be unique.
181e41f4b71Sopenharmony_ci                    deviceMatchAttr = "sample_config"; // Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
182e41f4b71Sopenharmony_ci                }
183e41f4b71Sopenharmony_ci            }
184e41f4b71Sopenharmony_ci        }
185e41f4b71Sopenharmony_ci    }
186e41f4b71Sopenharmony_ci}
187e41f4b71Sopenharmony_ci```
188e41f4b71Sopenharmony_ci
189e41f4b71Sopenharmony_ci#### [Rule] Use the defined types during driver model design and classification. Do not configure hosts and devices repeatedly.
190e41f4b71Sopenharmony_ci
191e41f4b71Sopenharmony_ci[Description] The HDF places the same type of devices in the same host. You can develop and deploy the driver functionalities of the host by layer, so that one driver has multiple nodes. The following figure shows the HDF driver model.
192e41f4b71Sopenharmony_ci
193e41f4b71Sopenharmony_ci![hdf-driver-model.png](figures/hdf-driver-model.png)
194e41f4b71Sopenharmony_ci
195e41f4b71Sopenharmony_ciPlace devices of the same type in the same host. When adding a device, check whether the host of the same type already exists. If such a host already exists, configure the device in the host. Do not configure the same host again. A device belongs to only one driver. Therefore, do not configure the same device in different hosts.
196e41f4b71Sopenharmony_ci
197e41f4b71Sopenharmony_ci#### [Rule] Set publication policies for driver services based on service rules.
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ci[Description] The driver service is the object of capabilities provided by the driver to external systems and is managed by the HDF in a unified manner. The HDF uses the **policy** field in the configuration file to define policies for drivers to publish services externally. The values and meanings of this field are as follows:
200e41f4b71Sopenharmony_ci
201e41f4b71Sopenharmony_ci```c
202e41f4b71Sopenharmony_citypedef enum {
203e41f4b71Sopenharmony_ci    /* The driver does not provide services.*/
204e41f4b71Sopenharmony_ci    SERVICE_POLICY_NONE = 0,
205e41f4b71Sopenharmony_ci    /* The driver provides services for kernel-space applications. */
206e41f4b71Sopenharmony_ci    SERVICE_POLICY_PUBLIC = 1,
207e41f4b71Sopenharmony_ci    /* The driver provides services for both kernel- and user-space applications. */
208e41f4b71Sopenharmony_ci    SERVICE_POLICY_CAPACITY = 2,
209e41f4b71Sopenharmony_ci    /** Driver services are not published externally but can be subscribed to. */
210e41f4b71Sopenharmony_ci    SERVICE_POLICY_FRIENDLY = 3,
211e41f4b71Sopenharmony_ci    /* Driver services are not published externally and cannot be subscribed to. */
212e41f4b71Sopenharmony_ci    SERVICE_POLICY_PRIVATE = 4,
213e41f4b71Sopenharmony_ci    /** Invalid policy. */
214e41f4b71Sopenharmony_ci    SERVICE_POLICY_INVALID
215e41f4b71Sopenharmony_ci} ServicePolicy;
216e41f4b71Sopenharmony_ci```
217e41f4b71Sopenharmony_ci
218e41f4b71Sopenharmony_ciYou must set the policies based on service rules. Do not set unnecessary policies, for example, setting user-mode publication policies for kernel-mode drivers.
219e41f4b71Sopenharmony_ci
220e41f4b71Sopenharmony_ci[Example]
221e41f4b71Sopenharmony_ci
222e41f4b71Sopenharmony_ci```
223e41f4b71Sopenharmony_ciroot {
224e41f4b71Sopenharmony_ci    device_info {
225e41f4b71Sopenharmony_ci        sample_host {
226e41f4b71Sopenharmony_ci            sample_device {
227e41f4b71Sopenharmony_ci                device0 {
228e41f4b71Sopenharmony_ci                    policy = 1; // The driver provides services for kernel-space applications. 
229e41f4b71Sopenharmony_ci                    ...
230e41f4b71Sopenharmony_ci                }
231e41f4b71Sopenharmony_ci            }
232e41f4b71Sopenharmony_ci        }
233e41f4b71Sopenharmony_ci    }
234e41f4b71Sopenharmony_ci}
235e41f4b71Sopenharmony_ci```
236e41f4b71Sopenharmony_ci
237e41f4b71Sopenharmony_ci#### [Rule] The permission to create device nodes for a driver must match the publication policy of the driver.
238e41f4b71Sopenharmony_ci
239e41f4b71Sopenharmony_ci[Description] In the **device_info.hcs** file, the **permission** field specifies the permission used by the driver to create a device node. This field is a 4-digit octal number and uses the Unix file permissions, for example, 0644. This field takes effect only when the driver provides services for user-space applications (policy = 2).
240e41f4b71Sopenharmony_ci
241e41f4b71Sopenharmony_ciYou must ensure that the publication policy of the driver service matches the device node permission. Otherwise, access to the driver service may fail or the permission of the device node may be inappropriate.
242e41f4b71Sopenharmony_ci
243e41f4b71Sopenharmony_ci[Example]
244e41f4b71Sopenharmony_ci
245e41f4b71Sopenharmony_ci```
246e41f4b71Sopenharmony_ciroot {
247e41f4b71Sopenharmony_ci    device_info {
248e41f4b71Sopenharmony_ci        sample_host {
249e41f4b71Sopenharmony_ci            sample_device {
250e41f4b71Sopenharmony_ci                device0 {
251e41f4b71Sopenharmony_ci                    policy = 2; // The driver provides services for both kernel- and user-space applications.
252e41f4b71Sopenharmony_ci                    permission = 0640; // Recommended value
253e41f4b71Sopenharmony_ci                    ...
254e41f4b71Sopenharmony_ci                }
255e41f4b71Sopenharmony_ci            }
256e41f4b71Sopenharmony_ci        }
257e41f4b71Sopenharmony_ci    }
258e41f4b71Sopenharmony_ci}
259e41f4b71Sopenharmony_ci```
260e41f4b71Sopenharmony_ci
261e41f4b71Sopenharmony_ci[Counterexample]
262e41f4b71Sopenharmony_ci
263e41f4b71Sopenharmony_ci```
264e41f4b71Sopenharmony_ciroot {
265e41f4b71Sopenharmony_ci    device_info {
266e41f4b71Sopenharmony_ci        sample_host {
267e41f4b71Sopenharmony_ci            sample_device {
268e41f4b71Sopenharmony_ci                device0 {
269e41f4b71Sopenharmony_ci                    policy = 2; // The driver provides services for both kernel- and user-space applications.
270e41f4b71Sopenharmony_ci                    permission = 0777; // Excessive permission.
271e41f4b71Sopenharmony_ci                    ...
272e41f4b71Sopenharmony_ci                }
273e41f4b71Sopenharmony_ci            }
274e41f4b71Sopenharmony_ci        }
275e41f4b71Sopenharmony_ci    }
276e41f4b71Sopenharmony_ci}
277e41f4b71Sopenharmony_ci```
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci[Counterexample]
280e41f4b71Sopenharmony_ci
281e41f4b71Sopenharmony_ci```
282e41f4b71Sopenharmony_ciroot {
283e41f4b71Sopenharmony_ci    device_info {
284e41f4b71Sopenharmony_ci        sample_host {
285e41f4b71Sopenharmony_ci            sample_device {
286e41f4b71Sopenharmony_ci                device0 {
287e41f4b71Sopenharmony_ci                    policy = 1; // The driver provides services for kernel-space applications but does not create a device node.
288e41f4b71Sopenharmony_ci                    permission = 0640; // Redundancy configuration
289e41f4b71Sopenharmony_ci                    ...
290e41f4b71Sopenharmony_ci                }
291e41f4b71Sopenharmony_ci            }
292e41f4b71Sopenharmony_ci        }
293e41f4b71Sopenharmony_ci    }
294e41f4b71Sopenharmony_ci}
295e41f4b71Sopenharmony_ci```
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ci#### [Rule] Configure whether to load a driver as required based on service requirements.
298e41f4b71Sopenharmony_ci
299e41f4b71Sopenharmony_ci[Description] In the **device_info.hcs**, **preload** specifies the driver loading mode. The values and meanings of this field are as follows:
300e41f4b71Sopenharmony_ci
301e41f4b71Sopenharmony_ci```c
302e41f4b71Sopenharmony_citypedef enum {
303e41f4b71Sopenharmony_ci    /* The driver is loaded by default during the system boot process. */
304e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_ENABLE = 0,
305e41f4b71Sopenharmony_ci    /* The driver is loaded after a quick start is complete if the system supports quick start. If the system does not support quick start, this value has the same meaning as DEVICE\_PRELOAD\_ENABLE. */
306e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_ENABLE_STEP2,
307e41f4b71Sopenharmony_ci    /* The driver is not loaded during the system boot process. When a user-mode process requests the driver service, the HDF attempts to dynamically load the driver if the driver service does not exist. */
308e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_DISABLE,
309e41f4b71Sopenharmony_ci    /** Invalid value. */
310e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_INVALID
311e41f4b71Sopenharmony_ci} DevicePreload;
312e41f4b71Sopenharmony_ci```
313e41f4b71Sopenharmony_ci
314e41f4b71Sopenharmony_ciSet the **preload** field based on the service requirements.
315e41f4b71Sopenharmony_ci
316e41f4b71Sopenharmony_ci[Example]
317e41f4b71Sopenharmony_ci
318e41f4b71Sopenharmony_ci```
319e41f4b71Sopenharmony_ciroot {
320e41f4b71Sopenharmony_ci    device_info {
321e41f4b71Sopenharmony_ci        sample_host {
322e41f4b71Sopenharmony_ci            sample_device {
323e41f4b71Sopenharmony_ci                device0 {
324e41f4b71Sopenharmony_ci                    preload = 2; // The driver is loaded as required.
325e41f4b71Sopenharmony_ci                    ...
326e41f4b71Sopenharmony_ci                }
327e41f4b71Sopenharmony_ci            }
328e41f4b71Sopenharmony_ci        }
329e41f4b71Sopenharmony_ci    }
330e41f4b71Sopenharmony_ci}
331e41f4b71Sopenharmony_ci```
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci#### [Rec] When the preload field is set to 0, configure the loading priority based on the service requirements.
334e41f4b71Sopenharmony_ci
335e41f4b71Sopenharmony_ci[Description] In the **device_info.hcs** file, the **priority** field indicates the host and driver loading priority. The value of this field is an integer ranging from 0 to 200. For drivers in different hosts, a smaller priority value of the host indicates a higher driver loading priority. For drivers in the same host, a smaller priority value of the driver indicates a higher driver loading priority. The default value of the **priority** field is 100. If this field is not set or set to the same value for different drivers, the driver loading sequence cannot be ensured. You should configure the **priority** field based on the service requirements to ensure the driver loading sequence.
336e41f4b71Sopenharmony_ci
337e41f4b71Sopenharmony_ci[Example]
338e41f4b71Sopenharmony_ci
339e41f4b71Sopenharmony_ci```
340e41f4b71Sopenharmony_ciroot {
341e41f4b71Sopenharmony_ci    device_info {
342e41f4b71Sopenharmony_ci        sample_host0 {
343e41f4b71Sopenharmony_ci        priority = 100;
344e41f4b71Sopenharmony_ci            sample_device {
345e41f4b71Sopenharmony_ci                device0 {
346e41f4b71Sopenharmony_ci                    preload = 0; // The driver is loaded by default.
347e41f4b71Sopenharmony_ci                    priority = 100; // The HDF ensures that the driver is loaded before device1.
348e41f4b71Sopenharmony_ci                    ...
349e41f4b71Sopenharmony_ci                }
350e41f4b71Sopenharmony_ci                device1 {
351e41f4b71Sopenharmony_ci                    preload = 0; // The driver is loaded by default.
352e41f4b71Sopenharmony_ci                    priority = 200; // The HDF ensures that the driver is loaded after device0.
353e41f4b71Sopenharmony_ci                    ...
354e41f4b71Sopenharmony_ci                }
355e41f4b71Sopenharmony_ci            }
356e41f4b71Sopenharmony_ci        }
357e41f4b71Sopenharmony_ci        sample_host1 {
358e41f4b71Sopenharmony_ci            priority = 100; // The HDF does not ensure the loading sequence because this host has the same priority as sample_host0.
359e41f4b71Sopenharmony_ci            ...
360e41f4b71Sopenharmony_ci        }
361e41f4b71Sopenharmony_ci    }
362e41f4b71Sopenharmony_ci}
363e41f4b71Sopenharmony_ci```
364e41f4b71Sopenharmony_ci
365e41f4b71Sopenharmony_ci**Private Configuration Information of the Driver**
366e41f4b71Sopenharmony_ci
367e41f4b71Sopenharmony_ciIf a driver has private configurations, you can add a driver configuration file to fill in default configurations of the driver. When loading the driver, the HDF obtains the configuration information, saves it in the **property** field of **HdfDeviceObject**, and passes it to the driver through **Bind** and **Init**.
368e41f4b71Sopenharmony_ci
369e41f4b71Sopenharmony_ci#### [Rule] Store the private configuration files of the drivers in different directories according to the component type or module.
370e41f4b71Sopenharmony_ci
371e41f4b71Sopenharmony_ci[Description] You must properly plan the directory for storing private configuration files of drivers. Do not store them in the root directory.
372e41f4b71Sopenharmony_ci
373e41f4b71Sopenharmony_ci[Example]
374e41f4b71Sopenharmony_ci
375e41f4b71Sopenharmony_ci```bash
376e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/sample/sample_config.hcs # Correct. The private configuration file is stored in the sample directory.
377e41f4b71Sopenharmony_ci
378e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/sample_config.hcs # Incorrect. The private configuration file is placed in the root directory.
379e41f4b71Sopenharmony_ci```
380e41f4b71Sopenharmony_ci
381e41f4b71Sopenharmony_ci#### [Rule] Add the private configuration file of a driver to the hdf.hcs file in the hdf_config directory.
382e41f4b71Sopenharmony_ci
383e41f4b71Sopenharmony_ci[Description] The **hdf.hcs** file summarizes the configuration information. The HDF parses the file content and loads the private configuration information of the driver to the device node during the build and runtime. Include the private configuration file of the driver in the **hdf.hcs** file to trigger driver initialization.
384e41f4b71Sopenharmony_ci
385e41f4b71Sopenharmony_ci[Example]
386e41f4b71Sopenharmony_ci
387e41f4b71Sopenharmony_ci```c
388e41f4b71Sopenharmony_ci#include "device_info/device_info.hcs"
389e41f4b71Sopenharmony_ci#include "sample/sample_config.hcs" // The file contains the private configuration file of a driver.
390e41f4b71Sopenharmony_ci
391e41f4b71Sopenharmony_ciroot {
392e41f4b71Sopenharmony_ci    module = "hisilicon,hi35xx_chip";
393e41f4b71Sopenharmony_ci}
394e41f4b71Sopenharmony_ci```
395e41f4b71Sopenharmony_ci
396e41f4b71Sopenharmony_ci#### [Rule] The value of the matchAttr field in the private configuration file of the driver must be the same as that of the deviceMatchAttr field in device_info.hcs.
397e41f4b71Sopenharmony_ci
398e41f4b71Sopenharmony_ci[Description] The HDF associates with the driver device through the **match_attr** field. A mismatch causes a failure to obtain the private configuration information.
399e41f4b71Sopenharmony_ci
400e41f4b71Sopenharmony_ci[Example]
401e41f4b71Sopenharmony_ci
402e41f4b71Sopenharmony_ci```
403e41f4b71Sopenharmony_ciroot {
404e41f4b71Sopenharmony_ci    sample_config {
405e41f4b71Sopenharmony_ci        ...
406e41f4b71Sopenharmony_ci        match_attr = "sample_config"; // The value of this field must be the same as that of deviceMatchAttr in device_info.hcs.
407e41f4b71Sopenharmony_ci    }
408e41f4b71Sopenharmony_ci}
409e41f4b71Sopenharmony_ci```
410e41f4b71Sopenharmony_ci
411e41f4b71Sopenharmony_ci#### [Rule] Use underscores (_) in field names in the private configuration file.
412e41f4b71Sopenharmony_ci
413e41f4b71Sopenharmony_ci[Description] According to the naming rules in the C/C++ coding guide, use underscores (_) in field names in the private configuration file of a driver. In this way, the naming rule is satisfied during the definition of the private configuration data structure in the implementation code. It also makes unified management of the code and configuration files easier.
414e41f4b71Sopenharmony_ci
415e41f4b71Sopenharmony_ci[Example]
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ci```
418e41f4b71Sopenharmony_ciroot {
419e41f4b71Sopenharmony_ci    sample_config {
420e41f4b71Sopenharmony_ci        sample_version = 1; // Use an underscore (_) in the field name.
421e41f4b71Sopenharmony_ci        sample_bus = "I2C_0";
422e41f4b71Sopenharmony_ci        match_attr = "sample_config";
423e41f4b71Sopenharmony_ci    }
424e41f4b71Sopenharmony_ci}
425e41f4b71Sopenharmony_ci```
426e41f4b71Sopenharmony_ci
427e41f4b71Sopenharmony_ci### HCS Macros
428e41f4b71Sopenharmony_ci
429e41f4b71Sopenharmony_ciThe private configuration information of a driver is loaded to **property** of **HdfDeviceObject**. This occupies memory space, which should be avoided for mini- and small-system devices. To minimize the memory usage, the HDF provides HCS macros to parse the private configuration information.
430e41f4b71Sopenharmony_ci
431e41f4b71Sopenharmony_ci#### [Rule] Use HCS macros to parse the private configuration information in memory-sensitive or cross-system scenario.
432e41f4b71Sopenharmony_ci
433e41f4b71Sopenharmony_ci[Description] You should specify the use cases of drivers. In memory-sensitive scenarios or if a driver needs to be used in mini-, small-, and standard-system devices, use HCS macros to parse the private configuration information for higher performance and portability.
434e41f4b71Sopenharmony_ci
435e41f4b71Sopenharmony_ci[Example]
436e41f4b71Sopenharmony_ci
437e41f4b71Sopenharmony_ci```c
438e41f4b71Sopenharmony_ci#include <utils/hcs_macro.h>
439e41f4b71Sopenharmony_ci
440e41f4b71Sopenharmony_ci#define SAMPLE_CONFIG_NODE HCS_NODE(HCS_ROOT, sample_config)
441e41f4b71Sopenharmony_ci
442e41f4b71Sopenharmony_ciASSERT_EQ(HCS_PROP(SAMPLE_CONFIG_NODE, sampleVersion), 1);
443e41f4b71Sopenharmony_ciASSERT_EQ(HCS_PROP(SAMPLE_CONFIG_NODE, sample_bus), "I2C_0");
444e41f4b71Sopenharmony_ciASSERT_EQ(HCS_PROP(SAMPLE_CONFIG_NODE, match_attr), "sample_config");
445e41f4b71Sopenharmony_ci```
446e41f4b71Sopenharmony_ci
447e41f4b71Sopenharmony_ci### HDF Tools
448e41f4b71Sopenharmony_ci
449e41f4b71Sopenharmony_ci#### [Rule] Determine the communication scenario and HdfSbuf type.
450e41f4b71Sopenharmony_ci
451e41f4b71Sopenharmony_ci[Description] **HdfSbuf** is a data structure used for data transfer. This structure is classified into different types based on the communication scenario. These types are defined in the **hdf_sbuf.h** header file.
452e41f4b71Sopenharmony_ci
453e41f4b71Sopenharmony_ci```c
454e41f4b71Sopenharmony_cienum HdfSbufType {
455e41f4b71Sopenharmony_ci    SBUF_RAW = 0,   /* SBUF used for communication between the user space and the kernel space. */
456e41f4b71Sopenharmony_ci    SBUF_IPC,      /* SBUF used for inter-process communication (IPC). */
457e41f4b71Sopenharmony_ci    SBUF_IPC_HW,    /* Reserved for extension. */
458e41f4b71Sopenharmony_ci    SBUF_TYPE_MAX,  /* Maximum value of the SBUF type. */
459e41f4b71Sopenharmony_ci};
460e41f4b71Sopenharmony_ci```
461e41f4b71Sopenharmony_ci
462e41f4b71Sopenharmony_ciDetermine whether the data transfer is IPC in the user space or between the user space and kernel space, and then create the corresponding **HdfSbuf** structure.
463e41f4b71Sopenharmony_ci
464e41f4b71Sopenharmony_ci[Example]
465e41f4b71Sopenharmony_ci
466e41f4b71Sopenharmony_ci```c
467e41f4b71Sopenharmony_civoid SampleDispatchBetweenUserAndKernel()
468e41f4b71Sopenharmony_ci{
469e41f4b71Sopenharmony_ci    int32_t ret;
470e41f4b71Sopenharmony_ci    /* Communication between the user space and kernel space. */
471e41f4b71Sopenharmony_ci    struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_RAW);
472e41f4b71Sopenharmony_ci    ...
473e41f4b71Sopenharmony_ci    ret = sample->dispatcher->Dispatch(&sample->object, CMD_SAMPLE_DISPATCH, data, NULL);
474e41f4b71Sopenharmony_ci    ...
475e41f4b71Sopenharmony_ci    HdfSBufRecycle(data);
476e41f4b71Sopenharmony_ci}
477e41f4b71Sopenharmony_ci```
478e41f4b71Sopenharmony_ci
479e41f4b71Sopenharmony_ci[Example]
480e41f4b71Sopenharmony_ci
481e41f4b71Sopenharmony_ci```c++
482e41f4b71Sopenharmony_civoid SampleDispatchIpc()
483e41f4b71Sopenharmony_ci{
484e41f4b71Sopenharmony_ci    /* IPC */
485e41f4b71Sopenharmony_ci    struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC);
486e41f4b71Sopenharmony_ci    ...
487e41f4b71Sopenharmony_ci    int ret = sample->dispatcher->Dispatch(sample, CMD_SAMPLE_DISPATCH, data, nullptr);
488e41f4b71Sopenharmony_ci    ...
489e41f4b71Sopenharmony_ci    HdfSBufRecycle(data);
490e41f4b71Sopenharmony_ci}
491e41f4b71Sopenharmony_ci```
492e41f4b71Sopenharmony_ci
493e41f4b71Sopenharmony_ci#### [Rule] Define the HDF_LOG_TAG macro when using HDF logging.
494e41f4b71Sopenharmony_ci
495e41f4b71Sopenharmony_ci[Description] The HDF provides the **hdf_log.h** tool ,using which you can output driver run logs. The **HDF_LOG_TAG** macro specifies the log tag. You must define this macro before printing logs.
496e41f4b71Sopenharmony_ci
497e41f4b71Sopenharmony_ci[Example]
498e41f4b71Sopenharmony_ci
499e41f4b71Sopenharmony_ci```c
500e41f4b71Sopenharmony_ci#include <hdf_log.h>
501e41f4b71Sopenharmony_ci
502e41f4b71Sopenharmony_ci#define HDF_LOG_TAG sample_driver // Define the log tag.
503e41f4b71Sopenharmony_ci
504e41f4b71Sopenharmony_ciint32_t SampleDriverInit(struct HdfDeviceObject *deviceObject)
505e41f4b71Sopenharmony_ci{
506e41f4b71Sopenharmony_ci    HDF_LOGI("sample driver is initialized"); // Use the tool to print logs.
507e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
508e41f4b71Sopenharmony_ci}
509e41f4b71Sopenharmony_ci```
510e41f4b71Sopenharmony_ci
511e41f4b71Sopenharmony_ci#### [Rule] Verify the return values of the HDF methods and use the error codes provided by the HDF.
512e41f4b71Sopenharmony_ci
513e41f4b71Sopenharmony_ci[Description] The HDF methods have specific return values. You should verify them rather than ignoring them. The return values correspond to error codes in the **hdf_base.h** header file. Use the error codes provided by the HDF when using the HDF or implementing custom methods.
514e41f4b71Sopenharmony_ci
515e41f4b71Sopenharmony_ci[Example]
516e41f4b71Sopenharmony_ci
517e41f4b71Sopenharmony_ci```c
518e41f4b71Sopenharmony_ciint32_t SampleDriverInit(struct HdfDeviceObject *deviceObject)
519e41f4b71Sopenharmony_ci{
520e41f4b71Sopenharmony_ci    int32_t ret;
521e41f4b71Sopenharmony_ci    // Check whether the device type is successfully set.
522e41f4b71Sopenharmony_ci    if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_DISPLAY)) {
523e41f4b71Sopenharmony_ci        HDF_LOGE("HdfDeviceSetClass failed");
524e41f4b71Sopenharmony_ci        return HDF_FAILURE;
525e41f4b71Sopenharmony_ci    }
526e41f4b71Sopenharmony_ci    ret = InitDiver();
527e41f4b71Sopenharmony_ci    // A custom method uses an error code provided by the HDF.
528e41f4b71Sopenharmony_ci    if (ret != HDF_SUCCESS) {
529e41f4b71Sopenharmony_ci        HDF_LOGE("init driver is failed");
530e41f4b71Sopenharmony_ci        return ret;
531e41f4b71Sopenharmony_ci    }
532e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
533e41f4b71Sopenharmony_ci}
534e41f4b71Sopenharmony_ci```
535e41f4b71Sopenharmony_ci
536e41f4b71Sopenharmony_ci### OSAL
537e41f4b71Sopenharmony_ci
538e41f4b71Sopenharmony_ciThe HDF OSAL shields the interface differences between OpenHarmony subsystems and provides unified OS interfaces, including memory management, threads, mutexes, spin locks, semaphores, timers, files, IRQ, time, atoms, firmware, and I/O operation modules.
539e41f4b71Sopenharmony_ci
540e41f4b71Sopenharmony_ci#### [Rule] Use OS interfaces through the OSAL for drivers used across mini-, small-, and standard-system devices.
541e41f4b71Sopenharmony_ci
542e41f4b71Sopenharmony_ci[Description] The OSAL shields the differences between OS interfaces. You should operate these OS interfaces based on the OSAL to ensure that drivers can run on different types of systems.
543e41f4b71Sopenharmony_ci
544e41f4b71Sopenharmony_ci[Example]
545e41f4b71Sopenharmony_ci
546e41f4b71Sopenharmony_ci```c
547e41f4b71Sopenharmony_ci#include <osal/osal_mem.h>
548e41f4b71Sopenharmony_ci#include <util/hdf_log.h>
549e41f4b71Sopenharmony_ci
550e41f4b71Sopenharmony_cistruct DevHandle *SampleInit(void)
551e41f4b71Sopenharmony_ci{
552e41f4b71Sopenharmony_ci    struct DevHandle *handle = (struct DevHandle *)OsalMemCalloc(sizeof(struct DevHandle));
553e41f4b71Sopenharmony_ci    if (handle == NULL) {
554e41f4b71Sopenharmony_ci        HDF_LOGE("OsalMemCalloc handle failed");
555e41f4b71Sopenharmony_ci        return NULL;
556e41f4b71Sopenharmony_ci    }
557e41f4b71Sopenharmony_ci    return handle;
558e41f4b71Sopenharmony_ci}
559e41f4b71Sopenharmony_ci```
560e41f4b71Sopenharmony_ci
561e41f4b71Sopenharmony_ci[Example]
562e41f4b71Sopenharmony_ci
563e41f4b71Sopenharmony_ci```c
564e41f4b71Sopenharmony_ci#include <osal/osal_time.h>
565e41f4b71Sopenharmony_ci
566e41f4b71Sopenharmony_civoid SampleSleep(uint32_t timeMs)
567e41f4b71Sopenharmony_ci{
568e41f4b71Sopenharmony_ci    OsalMSleep(timeMs);
569e41f4b71Sopenharmony_ci}
570e41f4b71Sopenharmony_ci```
571e41f4b71Sopenharmony_ci
572e41f4b71Sopenharmony_ci### PAL
573e41f4b71Sopenharmony_ci
574e41f4b71Sopenharmony_ciThe HDF PAL abstracts platform drivers and provides unified operation interfaces for modules such as the GPIO, I2C, SPI, UART, RTC, SDIO, eMMC, DSI, PWM, and watchdog.
575e41f4b71Sopenharmony_ci
576e41f4b71Sopenharmony_ci#### [Rule] Use platform drivers across mini, small, and standard systems through the PAL.
577e41f4b71Sopenharmony_ci
578e41f4b71Sopenharmony_ci[Description] The PAL masks the differences between platform driver interfaces of different system types. You should operate these interfaces based on PAL to ensure that drivers can run on different types of systems.
579e41f4b71Sopenharmony_ci
580e41f4b71Sopenharmony_ci[Example]
581e41f4b71Sopenharmony_ci
582e41f4b71Sopenharmony_ci```c
583e41f4b71Sopenharmony_ci#include <platform/gpio_if.h>
584e41f4b71Sopenharmony_ci#include <util/hdf_log.h>
585e41f4b71Sopenharmony_ci#include <osal/osal_irq.h>
586e41f4b71Sopenharmony_ci#include <osal/osal_time.h>
587e41f4b71Sopenharmony_ci
588e41f4b71Sopenharmony_cistatic uint32_t g_irqCnt;
589e41f4b71Sopenharmony_ci
590e41f4b71Sopenharmony_ci/* Sample function of the GPIO IRQ service */
591e41f4b71Sopenharmony_cistatic int32_t SampleGpioIrqHandler(uint16_t gpio, void *data)
592e41f4b71Sopenharmony_ci{
593e41f4b71Sopenharmony_ci    HDF_LOGE("%s: irq triggered, on gpio:%u, data=%p", __func__, gpio, data);
594e41f4b71Sopenharmony_ci    g_irqCnt++; /* If the IRQ function is triggered, the number of global counters is incremented by 1. */
595e41f4b71Sopenharmony_ci    return GpioDisableIrq(gpio);
596e41f4b71Sopenharmony_ci}
597e41f4b71Sopenharmony_ci
598e41f4b71Sopenharmony_ci/* GPIO sample function */
599e41f4b71Sopenharmony_cistatic int32_t SampleGpioIrqEdge(void)
600e41f4b71Sopenharmony_ci{
601e41f4b71Sopenharmony_ci    int32_t ret;
602e41f4b71Sopenharmony_ci    uint16_t valRead;
603e41f4b71Sopenharmony_ci    uint16_t mode;
604e41f4b71Sopenharmony_ci    uint16_t gpio = 83; // Number of the GPIO pin to test
605e41f4b71Sopenharmony_ci    uint32_t timeout;
606e41f4b71Sopenharmony_ci
607e41f4b71Sopenharmony_ci    /* Set the output direction for the pin. */
608e41f4b71Sopenharmony_ci    ret = GpioSetDir(gpio, GPIO_DIR_OUT);
609e41f4b71Sopenharmony_ci    ...
610e41f4b71Sopenharmony_ci    /* Disable the IRP of this pin. */
611e41f4b71Sopenharmony_ci    ret = GpioDisableIrq(gpio);
612e41f4b71Sopenharmony_ci    ...
613e41f4b71Sopenharmony_ci    /* Set the IRR function for the pin. The trigger mode is both rising edge and falling edge. */
614e41f4b71Sopenharmony_ci    mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING;
615e41f4b71Sopenharmony_ci    ret = GpioSetIrq(gpio, mode, SampleGpioIrqHandler, NULL);
616e41f4b71Sopenharmony_ci    ...
617e41f4b71Sopenharmony_ci    /* Enable the IRQ for this pin. */
618e41f4b71Sopenharmony_ci    ret = GpioEnableIrq(gpio);
619e41f4b71Sopenharmony_ci    ...
620e41f4b71Sopenharmony_ci    g_irqCnt = 0; /* Reset the global counter. */
621e41f4b71Sopenharmony_ci    timeout = 0;  /* Reset the waiting time. */
622e41f4b71Sopenharmony_ci    /* Wait for the IRQ function of this pin to trigger. The timeout duration is 1000 ms. */
623e41f4b71Sopenharmony_ci    while (g_irqCnt <= 0 && timeout < 1000) {
624e41f4b71Sopenharmony_ci        ret = GpioRead(gpio, &valRead);
625e41f4b71Sopenharmony_ci        ...
626e41f4b71Sopenharmony_ci        ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
627e41f4b71Sopenharmony_ci        ...
628e41f4b71Sopenharmony_ci        OsalMDelay(200); // Wait for an interrupt to be triggered.
629e41f4b71Sopenharmony_ci        timeout += 200;
630e41f4b71Sopenharmony_ci    }
631e41f4b71Sopenharmony_ci    ret = GpioUnSetIrq(gpio);
632e41f4b71Sopenharmony_ci    ...
633e41f4b71Sopenharmony_ci    return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE;
634e41f4b71Sopenharmony_ci}
635e41f4b71Sopenharmony_ci```
636