1e41f4b71Sopenharmony_ci# HDF Driver Development Process
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciThe Hardware Driver Foundation (HDF) provides a driver development framework to implement driver loading, driver service management, driver messaging mechanism, and configuration management. It provides a component-based driver model to normalize driver development and deployment. The HDF strives to build a unified driver platform to back up a more precise and efficient environment for one-time development for multi-device deployment.
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci### Driver Loading
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe HDF allows loading of the drivers that match the configured device list.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci### Driver Service Management
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ciThe HDF supports centralized management of driver services. You can obtain a driver service by using the APIs provided by the HDF.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci### Driver Messaging Mechanism
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ciThe HDF provides a unified driver messaging mechanism, which allows messages to be exchanged between user-mode applications and kernel-mode drivers.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci### Configuration Management
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ciHDF Configuration Source (HCS) provides the source code of the HDF configuration in key-value (KV) pairs. It decouples the configuration code from the driver code, thereby facilitating configuration management.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci### Driver Model
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ciThe device model involves the following concepts:
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ci- Host: In the HDF, the device drivers of the same type are placed in a host. The host manages the startup and loading of a group of devices.  You can deploy the drivers that depend on each other to the same host, and deploy independent drivers to different hosts.
28e41f4b71Sopenharmony_ci- Device: A device corresponds to a physical device.
29e41f4b71Sopenharmony_ci- Device Node: A device node is a component of a device. A device has at least one device node. Each device node can publish a device service. Each device node corresponds to a unique driver to interact with the hardware. 
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ciThe following figure shows the HDF driver model.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ci**Figure 1** HDF driver model
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci![](figures/hdf-driver-model.png)
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci## Driver Functions
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci### Driver Loading
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ciThe HDF implements loading of the drivers that match the configured device list. The drivers can be loaded on demand or in sequence. The **preload** field in the configuration file specifies the loading policy. The values of **preload** are as follows:
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci```c
44e41f4b71Sopenharmony_citypedef enum {
45e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_ENABLE = 0,
46e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_ENABLE_STEP2 = 1,
47e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_DISABLE = 2,
48e41f4b71Sopenharmony_ci    DEVICE_PRELOAD_INVALID
49e41f4b71Sopenharmony_ci} DevicePreload;
50e41f4b71Sopenharmony_ci```
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci#### On-Demand Loading
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci- **0** (**DEVICE_PRELOAD_ENABLE**): loads the driver during the system boot process.
55e41f4b71Sopenharmony_ci- **1** (**DEVICE_PRELOAD_ENABLE_STEP2**): loads the driver after a quick start is complete. If the system does not support quick start, the value **1** has the same meaning as **DEVICE_PRELOAD_ENABLE**.
56e41f4b71Sopenharmony_ci- **2** (**DEVICE_PRELOAD_DISABLE**): dynamically loads the driver after the system starts. If the driver service does not exist when a user-mode process attempts to obtain the driver service [messaging mechanism](#driver-messaging-mechanism), the HDF will dynamically load the driver.
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci#### Sequential Loading (Default)
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ciThe **priority** field (ranging from 0 to 200) in the configuration file determines the loading sequence of a host and a driver. For the drivers in different hosts, the driver with a smaller host priority is loaded first. For the drivers in the same host, the driver with a smaller priority is loaded first.
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci#### Exception Recovery (User-Mode Driver)
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ciThe policies for restoring from a driver service exception are as follows:
65e41f4b71Sopenharmony_ci- If **preload** is set to **0** (**DEVICE_PRELOAD_ENABLE**) or **1** (**DEVICE_PRELOAD_ENABLE_STEP2**) for the driver service, the startup module starts the host and reloads the service.
66e41f4b71Sopenharmony_ci- If **preload** is set to **2** (**DEVICE_PRELOAD_DISABLE**), the service module needs to register an HDF service status listener. When receiving a notification on service exit, the service module calls **LoadDevice()** to reload the service.
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci### Driver Service Management
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ciDriver services, as capability objects externally provided by HDF driver devices, are managed by the HDF in a unified manner. Driver service management involves publishing and obtaining driver services. The **policy** field in the configuration file defines the service publishing policies. The values of this field are as follows:
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci```c
73e41f4b71Sopenharmony_citypedef enum {
74e41f4b71Sopenharmony_ci    /* The driver does not provide services. */
75e41f4b71Sopenharmony_ci    SERVICE_POLICY_NONE = 0,
76e41f4b71Sopenharmony_ci    /* The driver publishes services only for kernel-mode processes. */
77e41f4b71Sopenharmony_ci    SERVICE_POLICY_PUBLIC = 1,
78e41f4b71Sopenharmony_ci    /* The driver publishes services for both kernel- and user-mode processes. */
79e41f4b71Sopenharmony_ci    SERVICE_POLICY_CAPACITY = 2,
80e41f4b71Sopenharmony_ci    /** The driver services are not published externally but can be subscribed to. */
81e41f4b71Sopenharmony_ci    SERVICE_POLICY_FRIENDLY = 3,
82e41f4b71Sopenharmony_ci    /* The driver private services cannot be published externally or subscribed to. */
83e41f4b71Sopenharmony_ci    SERVICE_POLICY_PRIVATE = 4,
84e41f4b71Sopenharmony_ci    /** Invalid service policy. */
85e41f4b71Sopenharmony_ci    SERVICE_POLICY_INVALID
86e41f4b71Sopenharmony_ci} ServicePolicy;
87e41f4b71Sopenharmony_ci```
88e41f4b71Sopenharmony_ci
89e41f4b71Sopenharmony_ci#### When to Use
90e41f4b71Sopenharmony_ci
91e41f4b71Sopenharmony_ciYou need to implement HDF driver service management when your driver needs to provide external capabilities via APIs.
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ci#### Available APIs
94e41f4b71Sopenharmony_ci
95e41f4b71Sopenharmony_ciThe following table describes the APIs for driver service management.
96e41f4b71Sopenharmony_ci
97e41f4b71Sopenharmony_ci**Table 1** APIs for driver service management
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci| API                                                        | Description                                                        |
100e41f4b71Sopenharmony_ci| ------------------------------------------------------------ | ------------------------------------------------------------ |
101e41f4b71Sopenharmony_ci| int32_t (*Bind)(struct HdfDeviceObject *deviceObject)        | Binds a service interface to the HDF. You need to implement **Bind**.|
102e41f4b71Sopenharmony_ci| const struct HdfObject *DevSvcManagerClntGetService(const char *svcName) | Obtains a driver service.                                            |
103e41f4b71Sopenharmony_ci| int HdfDeviceSubscribeService( struct HdfDeviceObject *deviceObject, const char *serviceName, struct SubscriberCallback callback) | Subscribes to a driver service.                                            |
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci### Driver Messaging Mechanism
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci#### When to Use
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ciThe HDF messaging mechanism implements interaction between the user-mode applications and kernel-mode drivers.
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci#### Available APIs
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ciThe messaging mechanism allows:
115e41f4b71Sopenharmony_ci- A user-mode application to send a message to a driver.
116e41f4b71Sopenharmony_ci- A user-mode application to receive events reported by a driver.
117e41f4b71Sopenharmony_ci
118e41f4b71Sopenharmony_ci**Table 2** APIs for the driver messaging mechanism
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci| API                                                          | Description                                                  |
121e41f4b71Sopenharmony_ci| ------------------------------------------------------------ | ------------------------------------------------------------ |
122e41f4b71Sopenharmony_ci| struct HdfIoService *HdfIoServiceBind(const char *serviceName); | Obtains a driver service. After obtaining the driver service, the user-mode application calls **Dispatch()** in the driver service obtained to send messages to the driver. |
123e41f4b71Sopenharmony_ci| void HdfIoServiceRecycle(struct HdfIoService *service);      | Releases a driver service.                                   |
124e41f4b71Sopenharmony_ci| int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener); | Registers an event listener to receive events from the driver. |
125e41f4b71Sopenharmony_ci| int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data) | Sends an event.                                              |
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci### Configuration Management
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci#### HDF Configuration Overview
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ciThe HCS provides the HDF configuration source code in KV pairs. It decouples the configuration code from the driver code, thereby facilitating configuration management. You can use the HDF Configuration Generator (HC-GEN) to convert an HCS configuration file into a file that can be read by the software.
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci-   In a low-performance system on a chip (SoC), the HC-GEN tool converts an HCS configuration file into the source code or macro definitions of the configuration tree. The driver can obtain the configuration by calling the C code or macro-based APIs.
136e41f4b71Sopenharmony_ci-   In a high-performance SoC, the tool converts an HCS configuration file into an HDF configuration binary (HCB) file. The driver can obtain the configuration by calling the configuration parsing APIs provided by the HDF.
137e41f4b71Sopenharmony_ci
138e41f4b71Sopenharmony_ciThe following figure illustrates the configuration management process.
139e41f4b71Sopenharmony_ci
140e41f4b71Sopenharmony_ci**Figure 2** Configuration management process
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ci![](figures/HCB-using-process.png)
143e41f4b71Sopenharmony_ci
144e41f4b71Sopenharmony_ciThe HC-GEN converts the HCS into an HCB file. The HCS Parser module in the HDF rebuilds a configuration tree from the HCB file. The HDF driver obtains the configuration through the APIs provided by the HCS Parser.
145e41f4b71Sopenharmony_ci
146e41f4b71Sopenharmony_ci#### Configuration Syntax
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ciThe following describes the HCS syntax.
149e41f4b71Sopenharmony_ci
150e41f4b71Sopenharmony_ci##### Keyword
151e41f4b71Sopenharmony_ci
152e41f4b71Sopenharmony_ciThe following table describes the keywords used in the HCS syntax.
153e41f4b71Sopenharmony_ci
154e41f4b71Sopenharmony_ci**Table 3** Keywords used in the HCS syntax
155e41f4b71Sopenharmony_ci
156e41f4b71Sopenharmony_ci| Keyword    | Description            | Remarks                               |
157e41f4b71Sopenharmony_ci| ---------- | -------------------------- | ------------------------------------------ |
158e41f4b71Sopenharmony_ci| root       | Sets the root node.                | -                                          |
159e41f4b71Sopenharmony_ci| include    | Includes another HCS file.       | -                                          |
160e41f4b71Sopenharmony_ci| delete     | Deletes a node or an attribute.            | Applicable only to the configuration tree imported by using **include**.           |
161e41f4b71Sopenharmony_ci| template   | Defines a template node.              | -                                          |
162e41f4b71Sopenharmony_ci| match_attr | Marks the node attribute for matching.| During configuration parsing, the attribute value can be used to locate the corresponding node.|
163e41f4b71Sopenharmony_ci
164e41f4b71Sopenharmony_ci##### Basic Structs
165e41f4b71Sopenharmony_ci
166e41f4b71Sopenharmony_ciThe HCS has two structs: **Attribute** and **Node**.
167e41f4b71Sopenharmony_ci
168e41f4b71Sopenharmony_ci**Attribute**
169e41f4b71Sopenharmony_ci
170e41f4b71Sopenharmony_ci**Attribute** is the minimum, independent configuration unit. The syntax is as follows:
171e41f4b71Sopenharmony_ci
172e41f4b71Sopenharmony_ci```
173e41f4b71Sopenharmony_ci  attribute_name = value;
174e41f4b71Sopenharmony_ci```
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ci-   **attribute_name** is a case-sensitive string consisting of letters, digits, and underscores (\_) and must start with a letter or underscore (_).
177e41f4b71Sopenharmony_ci-   The **value** can be in any of the following formats:
178e41f4b71Sopenharmony_ci    -   Numeric constant. The value can be a binary, octal, decimal, or hexadecimal number. For details, see [Data Types](#data-types).
179e41f4b71Sopenharmony_ci    -   String quoted by double quotation marks ("").
180e41f4b71Sopenharmony_ci    -   Node reference.
181e41f4b71Sopenharmony_ci-   An attribute key-value pair must end with a semicolon (;) and belong to a node.
182e41f4b71Sopenharmony_ci
183e41f4b71Sopenharmony_ci**Node**
184e41f4b71Sopenharmony_ci
185e41f4b71Sopenharmony_ci**Node** is a set of attributes. The syntax is as follows:
186e41f4b71Sopenharmony_ci
187e41f4b71Sopenharmony_ci```
188e41f4b71Sopenharmony_ci  node_name {
189e41f4b71Sopenharmony_ci      module = "sample";
190e41f4b71Sopenharmony_ci      ...
191e41f4b71Sopenharmony_ci  }
192e41f4b71Sopenharmony_ci```
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci-   **node_name** is a case-sensitive string consisting of letters, digits, and underscores (\_) and must start with a letter or underscore (_).
195e41f4b71Sopenharmony_ci-   No semicolon (;) is required after the curly brace ({) or (}).
196e41f4b71Sopenharmony_ci-   The keyword **root** is used to declare the root node of a configuration table. Each configuration table must start with the root node.
197e41f4b71Sopenharmony_ci-   The root node must contain a **module** attribute. The value is a string indicating the module to which the configuration belongs.
198e41f4b71Sopenharmony_ci-   The **match_attr** attribute can be added to a node. Its value is a globally unique string. When parsing the configuration, the driver can use the value of this attribute as a parameter to call an API to locate the node that has this attribute.
199e41f4b71Sopenharmony_ci
200e41f4b71Sopenharmony_ci##### Data Types
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_ciAttributes use built-in data types. You do not need to explicitly specify the data type for attribute values. Attributes support the following data types:
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci**Integer**
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ciAn integer can be in any of the following formats. The data type is assigned based on the actual data length and minimum space required.
207e41f4b71Sopenharmony_ci
208e41f4b71Sopenharmony_ci-   Binary: prefixed with **0b**. For example, **0b1010**.
209e41f4b71Sopenharmony_ci-   Octal: prefixed with **0**. For example, **0664**.
210e41f4b71Sopenharmony_ci-   Decimal: signed or unsigned, without prefix. For example, **1024** or **+1024**. Negative integers can be read only via APIs with signed numbers.
211e41f4b71Sopenharmony_ci-   Hexadecimal: prefixed with **0x**. For example, **0xff00** and **0xFF**.
212e41f4b71Sopenharmony_ci
213e41f4b71Sopenharmony_ci**String**
214e41f4b71Sopenharmony_ci
215e41f4b71Sopenharmony_ciA string is enclosed in double quotation marks ("").
216e41f4b71Sopenharmony_ci
217e41f4b71Sopenharmony_ci**Array**
218e41f4b71Sopenharmony_ci
219e41f4b71Sopenharmony_ciAn array can hold either integers or strings, but not both of them. The mixed use of **uint32_t** and **uint64_t** in an integer array will cause typecasting to **uint64**. The following is an example of an integer array and a string array:
220e41f4b71Sopenharmony_ci
221e41f4b71Sopenharmony_ci```
222e41f4b71Sopenharmony_ciattr_foo = [0x01, 0x02, 0x03, 0x04];
223e41f4b71Sopenharmony_ciattr_bar = ["hello", "world"];
224e41f4b71Sopenharmony_ci```
225e41f4b71Sopenharmony_ci
226e41f4b71Sopenharmony_ci**Boolean**
227e41f4b71Sopenharmony_ci
228e41f4b71Sopenharmony_ciBoolean is a form of data with only two possible values: **true** and **false**.
229e41f4b71Sopenharmony_ci
230e41f4b71Sopenharmony_ci##### Preprocessing
231e41f4b71Sopenharmony_ci
232e41f4b71Sopenharmony_ci**include**
233e41f4b71Sopenharmony_ci
234e41f4b71Sopenharmony_ciThe keyword **include** is used to import an HCS file. The syntax is as follows:
235e41f4b71Sopenharmony_ci
236e41f4b71Sopenharmony_ci```
237e41f4b71Sopenharmony_ci#include "foo.hcs"
238e41f4b71Sopenharmony_ci#include "../bar.hcs"
239e41f4b71Sopenharmony_ci```
240e41f4b71Sopenharmony_ci
241e41f4b71Sopenharmony_ci-   The file name must be enclosed in double quotation marks (""). If the file to be included is in a different directory with the target file, use a relative path. The included file must be a valid HCS file.
242e41f4b71Sopenharmony_ci-   If multiple HCS files included contain the same nodes, the same nodes will be overridden and other nodes are listed in sequence.
243e41f4b71Sopenharmony_ci
244e41f4b71Sopenharmony_ci##### Comments
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ciThe following two comment formats are supported:
247e41f4b71Sopenharmony_ci
248e41f4b71Sopenharmony_ci-   Single-line comment
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ci    ```
251e41f4b71Sopenharmony_ci    // comment
252e41f4b71Sopenharmony_ci    ```
253e41f4b71Sopenharmony_ci
254e41f4b71Sopenharmony_ci-   Multi-line comment
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ci    ```
257e41f4b71Sopenharmony_ci    /*
258e41f4b71Sopenharmony_ci    comment
259e41f4b71Sopenharmony_ci    */
260e41f4b71Sopenharmony_ci    ```
261e41f4b71Sopenharmony_ci
262e41f4b71Sopenharmony_ci    >   **NOTE**
263e41f4b71Sopenharmony_ci    >
264e41f4b71Sopenharmony_ci    >   Multi-line comments cannot be nested.
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ci##### Reference Modification
267e41f4b71Sopenharmony_ci
268e41f4b71Sopenharmony_ciYou can reference the content of a node to modify the content of another node. The syntax is as follows:
269e41f4b71Sopenharmony_ci
270e41f4b71Sopenharmony_ci```
271e41f4b71Sopenharmony_ci node :& source_node
272e41f4b71Sopenharmony_ci```
273e41f4b71Sopenharmony_ci
274e41f4b71Sopenharmony_ciIn this statement, the content of **node** is referenced to modify the content of **source_node**. <br>Example:
275e41f4b71Sopenharmony_ci
276e41f4b71Sopenharmony_ci```
277e41f4b71Sopenharmony_ciroot {
278e41f4b71Sopenharmony_ci    module = "sample";
279e41f4b71Sopenharmony_ci    foo {
280e41f4b71Sopenharmony_ci        foo_ :& root.bar{
281e41f4b71Sopenharmony_ci            attr = "foo";
282e41f4b71Sopenharmony_ci        }
283e41f4b71Sopenharmony_ci        foo1 :& foo2 {
284e41f4b71Sopenharmony_ci            attr = 0x2;
285e41f4b71Sopenharmony_ci        }
286e41f4b71Sopenharmony_ci        foo2 {
287e41f4b71Sopenharmony_ci            attr = 0x1;
288e41f4b71Sopenharmony_ci        }
289e41f4b71Sopenharmony_ci    }
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci    bar {
292e41f4b71Sopenharmony_ci        attr = "bar";
293e41f4b71Sopenharmony_ci    }
294e41f4b71Sopenharmony_ci}
295e41f4b71Sopenharmony_ci```
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ciThe configuration tree generated is as follows:
298e41f4b71Sopenharmony_ci
299e41f4b71Sopenharmony_ci```
300e41f4b71Sopenharmony_ciroot {
301e41f4b71Sopenharmony_ci    module = "sample";
302e41f4b71Sopenharmony_ci    foo {
303e41f4b71Sopenharmony_ci        foo2 {
304e41f4b71Sopenharmony_ci            attr = 0x2;
305e41f4b71Sopenharmony_ci        }
306e41f4b71Sopenharmony_ci    }
307e41f4b71Sopenharmony_ci    bar {
308e41f4b71Sopenharmony_ci        attr = "foo";
309e41f4b71Sopenharmony_ci    }
310e41f4b71Sopenharmony_ci}
311e41f4b71Sopenharmony_ci```
312e41f4b71Sopenharmony_ci
313e41f4b71Sopenharmony_ciIn this example, the value of **bar.attr** is changed to **foo** by referencing **foo.foo_**, and the value of **foo.foo2.attr** is changed to **0x2** by referencing **foo.foo1**. The **foo.foo_** and **foo.foo1** nodes are used to modify the content of the target nodes, and do not exist in the configuration tree generated.
314e41f4b71Sopenharmony_ci
315e41f4b71Sopenharmony_ci-   A node of the same level can be referenced simply by using the node name. To reference a node of a different level, use the absolute path starting with **root**, and separate the node names using a period (.). **root** indicates the root node. For example, **root.foo.bar**.
316e41f4b71Sopenharmony_ci-   If multiple modifications are made to the same attribute, only one modification takes effect and a warning will be displayed for you to confirm the result.
317e41f4b71Sopenharmony_ci
318e41f4b71Sopenharmony_ci##### Node Replication
319e41f4b71Sopenharmony_ci
320e41f4b71Sopenharmony_ciYou can replicate a node to define a node with similar content. The syntax is as follows:
321e41f4b71Sopenharmony_ci
322e41f4b71Sopenharmony_ci```
323e41f4b71Sopenharmony_ci node : source_node
324e41f4b71Sopenharmony_ci```
325e41f4b71Sopenharmony_ci
326e41f4b71Sopenharmony_ciThis statement replicates the attributes of the **source_node** node to define **node**. <br>Example:
327e41f4b71Sopenharmony_ci
328e41f4b71Sopenharmony_ci```
329e41f4b71Sopenharmony_ciroot {
330e41f4b71Sopenharmony_ci    module = "sample";
331e41f4b71Sopenharmony_ci    foo {
332e41f4b71Sopenharmony_ci        attr_0 = 0x0;
333e41f4b71Sopenharmony_ci    }
334e41f4b71Sopenharmony_ci    bar:foo {
335e41f4b71Sopenharmony_ci        attr_1 = 0x1;
336e41f4b71Sopenharmony_ci    }
337e41f4b71Sopenharmony_ci}
338e41f4b71Sopenharmony_ci```
339e41f4b71Sopenharmony_ci
340e41f4b71Sopenharmony_ciThe configuration tree generated is as follows:
341e41f4b71Sopenharmony_ci
342e41f4b71Sopenharmony_ci```
343e41f4b71Sopenharmony_ciroot {
344e41f4b71Sopenharmony_ci    module = "sample";
345e41f4b71Sopenharmony_ci    foo {
346e41f4b71Sopenharmony_ci        attr_0 = 0x0;
347e41f4b71Sopenharmony_ci    }
348e41f4b71Sopenharmony_ci    bar {
349e41f4b71Sopenharmony_ci        attr_1 = 0x1;
350e41f4b71Sopenharmony_ci        attr_0 = 0x0;
351e41f4b71Sopenharmony_ci    }
352e41f4b71Sopenharmony_ci}
353e41f4b71Sopenharmony_ci```
354e41f4b71Sopenharmony_ci
355e41f4b71Sopenharmony_ciIn this example, the **bar** node contains **attr_0** and **attr_1** attributes, and the modification of the **attr_0** attribute in the **bar** node does not affect the **foo** node.
356e41f4b71Sopenharmony_ci
357e41f4b71Sopenharmony_ciYou do not need to specify the path of the **foo** node if **foo** and **bar** are of the same level. Otherwise, you need to specify the absolute path of **foo** by using [Reference Modification](#reference-modification).
358e41f4b71Sopenharmony_ci
359e41f4b71Sopenharmony_ci##### Delete
360e41f4b71Sopenharmony_ci
361e41f4b71Sopenharmony_ciYou can use the keyword **delete** to delete unnecessary nodes or attributes from the base configuration tree imported by using the **include** keyword. The following example includes the configuration in **sample2.hcs** to **sample1.hcs** and deletes the **attribute2** attribute and the **foo_2** node. <br>Example:
362e41f4b71Sopenharmony_ci
363e41f4b71Sopenharmony_ci```
364e41f4b71Sopenharmony_ci// sample2.hcs
365e41f4b71Sopenharmony_ciroot {
366e41f4b71Sopenharmony_ci    attr_1 = 0x1;
367e41f4b71Sopenharmony_ci    attr_2 = 0x2;
368e41f4b71Sopenharmony_ci    foo_2 {
369e41f4b71Sopenharmony_ci        t = 0x1;
370e41f4b71Sopenharmony_ci    }
371e41f4b71Sopenharmony_ci}
372e41f4b71Sopenharmony_ci
373e41f4b71Sopenharmony_ci// sample1.hcs
374e41f4b71Sopenharmony_ci#include "sample2.hcs"
375e41f4b71Sopenharmony_ciroot {
376e41f4b71Sopenharmony_ci    attr_2 = delete;
377e41f4b71Sopenharmony_ci    foo_2 : delete {
378e41f4b71Sopenharmony_ci    }
379e41f4b71Sopenharmony_ci}
380e41f4b71Sopenharmony_ci```
381e41f4b71Sopenharmony_ci
382e41f4b71Sopenharmony_ciThe configuration tree generated is as follows:
383e41f4b71Sopenharmony_ci
384e41f4b71Sopenharmony_ci```
385e41f4b71Sopenharmony_ciroot {
386e41f4b71Sopenharmony_ci    attr_1 = 0x1;
387e41f4b71Sopenharmony_ci}
388e41f4b71Sopenharmony_ci```
389e41f4b71Sopenharmony_ci
390e41f4b71Sopenharmony_ci>   **NOTE**<br>
391e41f4b71Sopenharmony_ci>   The keyword **delete** cannot be used to delete nodes or attributes in the same HCS file. In an HCS file, you can directly delete unnecessary attributes.
392e41f4b71Sopenharmony_ci
393e41f4b71Sopenharmony_ci##### Attribute References
394e41f4b71Sopenharmony_ci
395e41f4b71Sopenharmony_ciYou can associate an attribute and a node so that the node can be quickly located when the attribute is read during configuration parsing. The syntax is as follows:
396e41f4b71Sopenharmony_ci
397e41f4b71Sopenharmony_ci```
398e41f4b71Sopenharmony_ci attribute = &node;
399e41f4b71Sopenharmony_ci```
400e41f4b71Sopenharmony_ci
401e41f4b71Sopenharmony_ciIn this statement, the value of **attribute** is a referenced to the node. During code parsing, you can quickly locate the node based on this **attribute**. <br>Example:
402e41f4b71Sopenharmony_ci
403e41f4b71Sopenharmony_ci```
404e41f4b71Sopenharmony_cinode1 {
405e41f4b71Sopenharmony_ci    attributes;
406e41f4b71Sopenharmony_ci}
407e41f4b71Sopenharmony_cinode2 {
408e41f4b71Sopenharmony_ci    attr_1 = &root.node1;
409e41f4b71Sopenharmony_ci}
410e41f4b71Sopenharmony_ci```
411e41f4b71Sopenharmony_ci
412e41f4b71Sopenharmony_cior
413e41f4b71Sopenharmony_ci
414e41f4b71Sopenharmony_ci```
415e41f4b71Sopenharmony_cinode2 {
416e41f4b71Sopenharmony_ci    node1 {
417e41f4b71Sopenharmony_ci        attributes;
418e41f4b71Sopenharmony_ci    }
419e41f4b71Sopenharmony_ci    attr_1 = &node1;
420e41f4b71Sopenharmony_ci}
421e41f4b71Sopenharmony_ci```
422e41f4b71Sopenharmony_ci
423e41f4b71Sopenharmony_ci##### Template
424e41f4b71Sopenharmony_ci
425e41f4b71Sopenharmony_ciThe template is used to generate nodes with consistent syntax, thereby facilitating the traverse and management of nodes of the same type. If a node is defined using the keyword **template**, its child nodes inherit from the node configuration through the double colon operator (::). The child nodes can modify or add but cannot delete attributes in **template**. The attributes not defined in the child nodes will use the attributes defined in **template** as the default values. <br>Example:
426e41f4b71Sopenharmony_ci
427e41f4b71Sopenharmony_ci```
428e41f4b71Sopenharmony_ciroot {
429e41f4b71Sopenharmony_ci    module = "sample";
430e41f4b71Sopenharmony_ci    template foo {
431e41f4b71Sopenharmony_ci        attr_1 = 0x1;
432e41f4b71Sopenharmony_ci        attr_2 = 0x2;
433e41f4b71Sopenharmony_ci    }
434e41f4b71Sopenharmony_ci
435e41f4b71Sopenharmony_ci    bar :: foo {
436e41f4b71Sopenharmony_ci    }
437e41f4b71Sopenharmony_ci
438e41f4b71Sopenharmony_ci    bar_1 :: foo {
439e41f4b71Sopenharmony_ci        attr_1 = 0x2;
440e41f4b71Sopenharmony_ci    }
441e41f4b71Sopenharmony_ci}
442e41f4b71Sopenharmony_ci```
443e41f4b71Sopenharmony_ci
444e41f4b71Sopenharmony_ci The configuration tree generated is as follows:
445e41f4b71Sopenharmony_ci
446e41f4b71Sopenharmony_ci```
447e41f4b71Sopenharmony_ciroot {
448e41f4b71Sopenharmony_ci    module = "sample";
449e41f4b71Sopenharmony_ci    bar {
450e41f4b71Sopenharmony_ci        attr_1 = 0x1;
451e41f4b71Sopenharmony_ci        attr_2 = 0x2;
452e41f4b71Sopenharmony_ci    }
453e41f4b71Sopenharmony_ci    bar_1 {
454e41f4b71Sopenharmony_ci        attr_1 = 0x2;
455e41f4b71Sopenharmony_ci        attr_2 = 0x2;
456e41f4b71Sopenharmony_ci    }
457e41f4b71Sopenharmony_ci}
458e41f4b71Sopenharmony_ci```
459e41f4b71Sopenharmony_ci
460e41f4b71Sopenharmony_ciIn this example, the **bar** and **bar_1** nodes inherit from the **foo** node. The structure of the generated configuration tree is the same as that of the **foo** node, except that the attribute values are different.
461e41f4b71Sopenharmony_ci
462e41f4b71Sopenharmony_ci#### Configuration Generation
463e41f4b71Sopenharmony_ci
464e41f4b71Sopenharmony_ciThe HC-GEN tool checks the HCS configuration syntax and converts HCS source files into HCB files.
465e41f4b71Sopenharmony_ci
466e41f4b71Sopenharmony_ci**HC-GEN**
467e41f4b71Sopenharmony_ci
468e41f4b71Sopenharmony_ciHC-GEN options:
469e41f4b71Sopenharmony_ci
470e41f4b71Sopenharmony_ci```
471e41f4b71Sopenharmony_ciUsage: hc-gen [Options] [File]
472e41f4b71Sopenharmony_cioptions:
473e41f4b71Sopenharmony_ci  -o <file>   output file name, default same as input
474e41f4b71Sopenharmony_ci  -a          hcb align with four bytes
475e41f4b71Sopenharmony_ci  -b          output binary output, default enable
476e41f4b71Sopenharmony_ci  -t          output config in C language source file style
477e41f4b71Sopenharmony_ci  -m          output config in macro source file style
478e41f4b71Sopenharmony_ci  -i          output binary hex dump in C language source file style
479e41f4b71Sopenharmony_ci  -p <prefix> prefix of generated symbol name
480e41f4b71Sopenharmony_ci  -d          decompile hcb to hcs
481e41f4b71Sopenharmony_ci  -V          show verbose info
482e41f4b71Sopenharmony_ci  -v          show version
483e41f4b71Sopenharmony_ci  -h          show this help message
484e41f4b71Sopenharmony_ci```
485e41f4b71Sopenharmony_ci
486e41f4b71Sopenharmony_ciGenerate a .c or .h configuration file.
487e41f4b71Sopenharmony_ci
488e41f4b71Sopenharmony_ci```
489e41f4b71Sopenharmony_cihc-gen -o [OutputCFileName] -t [SourceHcsFileName]
490e41f4b71Sopenharmony_ci```
491e41f4b71Sopenharmony_ci
492e41f4b71Sopenharmony_ciGenerate an HCB file.
493e41f4b71Sopenharmony_ci
494e41f4b71Sopenharmony_ci```
495e41f4b71Sopenharmony_cihc-gen -o [OutputHcbFileName] -b [SourceHcsFileName]
496e41f4b71Sopenharmony_ci```
497e41f4b71Sopenharmony_ci
498e41f4b71Sopenharmony_ciGenerate a macro definition file.
499e41f4b71Sopenharmony_ci
500e41f4b71Sopenharmony_ci```
501e41f4b71Sopenharmony_cihc-gen -o [OutputMacroFileName] -m [SourceHcsFileName]
502e41f4b71Sopenharmony_ci```
503e41f4b71Sopenharmony_ci
504e41f4b71Sopenharmony_ciDecompile an HCB file to an HCS file.
505e41f4b71Sopenharmony_ci
506e41f4b71Sopenharmony_ci```
507e41f4b71Sopenharmony_cihc-gen -o [OutputHcsFileName] -d [SourceHcbFileName]
508e41f4b71Sopenharmony_ci```
509e41f4b71Sopenharmony_ci
510e41f4b71Sopenharmony_ci## Development
511e41f4b71Sopenharmony_ci
512e41f4b71Sopenharmony_ci### When to Use
513e41f4b71Sopenharmony_ci
514e41f4b71Sopenharmony_ciDuring driver development, the driver cannot be loaded in the code compilation process without service management and messaging mechanism. The following describes the driver development process.
515e41f4b71Sopenharmony_ci
516e41f4b71Sopenharmony_ci### Driver Development Example
517e41f4b71Sopenharmony_ci
518e41f4b71Sopenharmony_ciThe HDF-based driver development involves the following:<br>1. Implement the driver.<br>2. Write the driver build script.<br>3. Configure the driver.
519e41f4b71Sopenharmony_ci
520e41f4b71Sopenharmony_ci#### Implementing a Driver
521e41f4b71Sopenharmony_ci
522e41f4b71Sopenharmony_ciWrite the driver code and register the driver entry with the HDF.
523e41f4b71Sopenharmony_ci
524e41f4b71Sopenharmony_ci-   Write the driver service code.<br>Example:
525e41f4b71Sopenharmony_ci
526e41f4b71Sopenharmony_ci    ```c
527e41f4b71Sopenharmony_ci    #include "hdf_device_desc.h"          // Include the driver development APIs provided by the HDF.
528e41f4b71Sopenharmony_ci    #include "hdf_log.h"                  // Include the log APIs provided by the HDF.
529e41f4b71Sopenharmony_ci
530e41f4b71Sopenharmony_ci    #define HDF_LOG_TAG "sample_driver"   // Define the tag contained in logs. If no tag is defined, the default HDF_TAG is used.
531e41f4b71Sopenharmony_ci
532e41f4b71Sopenharmony_ci    // Bind the service capability interface provided by the driver to the HDF.
533e41f4b71Sopenharmony_ci    int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
534e41f4b71Sopenharmony_ci    {
535e41f4b71Sopenharmony_ci        HDF_LOGD("Sample driver bind success");
536e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
537e41f4b71Sopenharmony_ci    }
538e41f4b71Sopenharmony_ci
539e41f4b71Sopenharmony_ci    // Initialize the driver service.
540e41f4b71Sopenharmony_ci    int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
541e41f4b71Sopenharmony_ci    {
542e41f4b71Sopenharmony_ci        HDF_LOGD("Sample driver Init success");
543e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
544e41f4b71Sopenharmony_ci    }
545e41f4b71Sopenharmony_ci
546e41f4b71Sopenharmony_ci    // Release the driver resources.
547e41f4b71Sopenharmony_ci    void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
548e41f4b71Sopenharmony_ci    {
549e41f4b71Sopenharmony_ci        HDF_LOGD("Sample driver release success");
550e41f4b71Sopenharmony_ci        return;
551e41f4b71Sopenharmony_ci    }
552e41f4b71Sopenharmony_ci    ```
553e41f4b71Sopenharmony_ci
554e41f4b71Sopenharmony_ci-   Register the driver entry with the HDF.
555e41f4b71Sopenharmony_ci
556e41f4b71Sopenharmony_ci    ```c
557e41f4b71Sopenharmony_ci    // Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h).
558e41f4b71Sopenharmony_ci    struct HdfDriverEntry g_sampleDriverEntry = {
559e41f4b71Sopenharmony_ci        .moduleVersion = 1,
560e41f4b71Sopenharmony_ci        .moduleName = "sample_driver",
561e41f4b71Sopenharmony_ci        .Bind = HdfSampleDriverBind,
562e41f4b71Sopenharmony_ci        .Init = HdfSampleDriverInit,
563e41f4b71Sopenharmony_ci        .Release = HdfSampleDriverRelease,
564e41f4b71Sopenharmony_ci    };
565e41f4b71Sopenharmony_ci
566e41f4b71Sopenharmony_ci    // Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls Bind() and then Init(). If Init() fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
567e41f4b71Sopenharmony_ci    HDF_INIT(g_sampleDriverEntry);
568e41f4b71Sopenharmony_ci    ```
569e41f4b71Sopenharmony_ci
570e41f4b71Sopenharmony_ci#### Writing the Driver Compilation Script
571e41f4b71Sopenharmony_ci
572e41f4b71Sopenharmony_ci- ##### LiteOS
573e41f4b71Sopenharmony_ci
574e41f4b71Sopenharmony_ci  If a LiteOS is used, you need to modify **makefile** and **BUILD.gn** files.
575e41f4b71Sopenharmony_ci
576e41f4b71Sopenharmony_ci  - **Makefile**:
577e41f4b71Sopenharmony_ci
578e41f4b71Sopenharmony_ci    Use the **makefile** template provided by the HDF to compile the driver code.
579e41f4b71Sopenharmony_ci
580e41f4b71Sopenharmony_ci    ```makefile
581e41f4b71Sopenharmony_ci    include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # (Mandatory) Import the HDF predefined content.
582e41f4b71Sopenharmony_ci    MODULE_NAME :=        # File to be generated.
583e41f4b71Sopenharmony_ci    LOCAL_INCLUDE: =      # Directory of the driver header files.
584e41f4b71Sopenharmony_ci    LOCAL_SRCS : =         # Source code files of the driver.
585e41f4b71Sopenharmony_ci    LOCAL_CFLAGS : =      # Custom compiler options.
586e41f4b71Sopenharmony_ci    include $(HDF_DRIVER) # Import the Makefile template to complete the build.
587e41f4b71Sopenharmony_ci    ```
588e41f4b71Sopenharmony_ci
589e41f4b71Sopenharmony_ci    Add the path of the generated file to **hdf_lite.mk** in the **drivers/hdf_core/adapter/khdf/liteos** directory to link the file to the kernel image.
590e41f4b71Sopenharmony_ci
591e41f4b71Sopenharmony_ci    Example:
592e41f4b71Sopenharmony_ci
593e41f4b71Sopenharmony_ci    ```makefile
594e41f4b71Sopenharmony_ci    LITEOS_BASELIB += -lxxx   # Static library generated by the link.
595e41f4b71Sopenharmony_ci    LIB_SUBDIRS    +=         # Directory in which makefile is located.
596e41f4b71Sopenharmony_ci    ```
597e41f4b71Sopenharmony_ci
598e41f4b71Sopenharmony_ci  -   **BUILD.gn**:
599e41f4b71Sopenharmony_ci
600e41f4b71Sopenharmony_ci      Add the module **BUILD.gn**.
601e41f4b71Sopenharmony_ci
602e41f4b71Sopenharmony_ci      Example:
603e41f4b71Sopenharmony_ci
604e41f4b71Sopenharmony_ci      ```
605e41f4b71Sopenharmony_ci      import("//build/lite/config/component/lite_component.gni")
606e41f4b71Sopenharmony_ci      import("//drivers/hdf_core/adapter/khdf/liteos/hdf.gni")
607e41f4b71Sopenharmony_ci      module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
608e41f4b71Sopenharmony_ci      module_name = "xxx"
609e41f4b71Sopenharmony_ci      hdf_driver(module_name) {
610e41f4b71Sopenharmony_ci          sources = [
611e41f4b71Sopenharmony_ci              "xxx/xxx/xxx.c",           # Source code to compile.
612e41f4b71Sopenharmony_ci          ]
613e41f4b71Sopenharmony_ci          public_configs = [ ":public" ] # Head file configuration of the dependencies.
614e41f4b71Sopenharmony_ci      }
615e41f4b71Sopenharmony_ci      config("public") {                 # Define the head file configuration of the dependencies.
616e41f4b71Sopenharmony_ci          include_dirs = [
617e41f4b71Sopenharmony_ci              "xxx/xxx/xxx",             # Directory of dependency header files.
618e41f4b71Sopenharmony_ci          ]
619e41f4b71Sopenharmony_ci  }
620e41f4b71Sopenharmony_ci      ```
621e41f4b71Sopenharmony_ci
622e41f4b71Sopenharmony_ci      Add the **BUILD.gn** directory to **/drivers/hdf_core/adapter/khdf/liteos/BUILD.gn**.
623e41f4b71Sopenharmony_ci
624e41f4b71Sopenharmony_ci      ```
625e41f4b71Sopenharmony_ci      group("liteos") {
626e41f4b71Sopenharmony_ci          public_deps = [ ":$module_name" ]
627e41f4b71Sopenharmony_ci          deps = [
628e41f4b71Sopenharmony_ci              "xxx/xxx", # Directory of the new module BUILD.gn, /drivers/hdf_core/adapter/khdf/liteos
629e41f4b71Sopenharmony_ci          ]
630e41f4b71Sopenharmony_ci      }
631e41f4b71Sopenharmony_ci      ```
632e41f4b71Sopenharmony_ci
633e41f4b71Sopenharmony_ci-   ##### Linux
634e41f4b71Sopenharmony_ci
635e41f4b71Sopenharmony_ci    To define the driver control macro, add the **Kconfig** file to the driver directory **xxx** and add the path of the **Kconfig** file to **drivers/hdf_core/adapter/khdf/linux/Kconfig**.
636e41f4b71Sopenharmony_ci
637e41f4b71Sopenharmony_ci    ```
638e41f4b71Sopenharmony_ci    source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
639e41f4b71Sopenharmony_ci    ```
640e41f4b71Sopenharmony_ci
641e41f4b71Sopenharmony_ci    Add the driver directory to **drivers/hdf_core/adapter/khdf/linux/Makefile**.
642e41f4b71Sopenharmony_ci
643e41f4b71Sopenharmony_ci    ```makefile
644e41f4b71Sopenharmony_ci    obj-$(CONFIG_DRIVERS_HDF)  += xxx/
645e41f4b71Sopenharmony_ci    ```
646e41f4b71Sopenharmony_ci
647e41f4b71Sopenharmony_ci    Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
648e41f4b71Sopenharmony_ci
649e41f4b71Sopenharmony_ci    ```makefile
650e41f4b71Sopenharmony_ci    obj-y  += xxx.o
651e41f4b71Sopenharmony_ci    ```
652e41f4b71Sopenharmony_ci
653e41f4b71Sopenharmony_ci#### Configuring the Driver
654e41f4b71Sopenharmony_ci
655e41f4b71Sopenharmony_ciThe HDF uses HCS as the configuration description source code. For details about the HCS, see [HDF Configuration Overview](#hdf-configuration-overview).
656e41f4b71Sopenharmony_ci
657e41f4b71Sopenharmony_ciThe driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
658e41f4b71Sopenharmony_ci
659e41f4b71Sopenharmony_ci- (Mandatory) Set driver device information.
660e41f4b71Sopenharmony_ci
661e41f4b71Sopenharmony_ci  The HDF loads a driver based on the driver device description defined by the HDF. Therefore, the driver device description must be added to the **device_info.hcs** file defined by the HDF.
662e41f4b71Sopenharmony_ci
663e41f4b71Sopenharmony_ci  Example:
664e41f4b71Sopenharmony_ci
665e41f4b71Sopenharmony_ci  ```
666e41f4b71Sopenharmony_ci  root {
667e41f4b71Sopenharmony_ci      device_info {
668e41f4b71Sopenharmony_ci          match_attr = "hdf_manager";
669e41f4b71Sopenharmony_ci          template host {       // Host template. If a node (for example, sample_host) uses the default values in this template, the node fields can be omitted.
670e41f4b71Sopenharmony_ci              hostName = "";
671e41f4b71Sopenharmony_ci              priority = 100;
672e41f4b71Sopenharmony_ci              uid = "";        // User ID (UID) of the user-mode process. It is left empty by default. If you do not set the value, this parameter will be set to the value of hostName, which indicates a common user.
673e41f4b71Sopenharmony_ci              gid = "";        // Group ID (GID) of the user-mode process. It is left empty by default. If you do not set the value, this parameter will be set to the value of hostName, which indicates a common user group.
674e41f4b71Sopenharmony_ci              caps = [""]];     // Linux capabilities of the user-mode process. It is left empty by default. Set this parameter based on service requirements.
675e41f4b71Sopenharmony_ci              template device {
676e41f4b71Sopenharmony_ci                  template deviceNode {
677e41f4b71Sopenharmony_ci                      policy = 0;
678e41f4b71Sopenharmony_ci                      priority = 100;
679e41f4b71Sopenharmony_ci                      preload = 0;
680e41f4b71Sopenharmony_ci                      permission = 0664;
681e41f4b71Sopenharmony_ci                      moduleName = "";
682e41f4b71Sopenharmony_ci                      serviceName = "";
683e41f4b71Sopenharmony_ci                      deviceMatchAttr = "";
684e41f4b71Sopenharmony_ci                  }
685e41f4b71Sopenharmony_ci              }
686e41f4b71Sopenharmony_ci          }
687e41f4b71Sopenharmony_ci          sample_host :: host{
688e41f4b71Sopenharmony_ci              hostName = "host0";    // Host name. The host node is used as a container to hold a type of drivers.
689e41f4b71Sopenharmony_ci              priority = 100;        // Host startup priority (0-200). A smaller value indicates a higher priority. The default value 100 is recommended. The hosts with the same priority start based on the time when the priority was configured. The host configured first starts first.
690e41f4b71Sopenharmony_ci              caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"];   // Linux capabilities of a user-mode process.
691e41f4b71Sopenharmony_ci              device_sample :: device {        // Sample device node.
692e41f4b71Sopenharmony_ci                  device0 :: deviceNode {      // DeviceNode of the sample driver.
693e41f4b71Sopenharmony_ci                      policy = 1;              // Policy for publishing the driver service. For details, see Driver Service Management.
694e41f4b71Sopenharmony_ci                      priority = 100;          // Driver startup priority (0-200). A smaller value indicates a higher priority. The default value 100 is recommended. The drivers with the same priority start based on the time when the priority was configured. The driver configured first starts first.
695e41f4b71Sopenharmony_ci                      preload = 0;             // The value 0 means to load the driver by default during the startup of the system.
696e41f4b71Sopenharmony_ci                      permission = 0664;       // Permission for the DeviceNode created.
697e41f4b71Sopenharmony_ci                      moduleName = "sample_driver";      // Driver name. The value must be the same as that of moduleName in the HdfDriverEntry structure.
698e41f4b71Sopenharmony_ci                      serviceName = "sample_service";    // Name of the service published by the driver. The service name must be unique.
699e41f4b71Sopenharmony_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.
700e41f4b71Sopenharmony_ci                  }
701e41f4b71Sopenharmony_ci              }
702e41f4b71Sopenharmony_ci          }
703e41f4b71Sopenharmony_ci      }
704e41f4b71Sopenharmony_ci  }
705e41f4b71Sopenharmony_ci  ```
706e41f4b71Sopenharmony_ci
707e41f4b71Sopenharmony_ci  >   **NOTE**<br>
708e41f4b71Sopenharmony_ci  >
709e41f4b71Sopenharmony_ci  >   -   **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
710e41f4b71Sopenharmony_ci  >   -   According to the principle of least privilege for processes, **uid** and **gid** do not need to be configured for service modules. In the preceding example, **uid** and **gid** are left empty (granted with the common user rights) for sample_host.
711e41f4b71Sopenharmony_ci  >   -   If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
712e41f4b71Sopenharmony_ci  >   -   The process UIDs are configured in **base/startup/init/services/etc/passwd**, and the process GIDs are configured in **base/startup/init/services/etc/group**. For details, see [Adding a System Service User Group]( https://gitee.com/openharmony/startup_init_lite/wikis).
713e41f4b71Sopenharmony_ci  >   -   The **caps** value is in the caps = ["xxx"] format. To configure **CAP_DAC_OVERRIDE**, set this parameter to **caps = ["DAC_OVERRIDE"]**. Do not set it to **caps = ["CAP_DAC_OVERRIDE"]**.
714e41f4b71Sopenharmony_ci  >   -   **preload** specifies the loading policy for the driver.
715e41f4b71Sopenharmony_ci
716e41f4b71Sopenharmony_ci-   (Optional) Set driver private information.
717e41f4b71Sopenharmony_ci
718e41f4b71Sopenharmony_ci    If the driver has private configuration, add a driver configuration file to set default driver configuration. When loading the driver, the HDF obtains and saves the driver private information in **property** of **HdfDeviceObject**, and passes the information to the driver using **Bind()** and **Init()** (see [Implementing a Driver](implementing-a-driver)). 
719e41f4b71Sopenharmony_ci
720e41f4b71Sopenharmony_ci    Example:
721e41f4b71Sopenharmony_ci
722e41f4b71Sopenharmony_ci    ```
723e41f4b71Sopenharmony_ci    root {
724e41f4b71Sopenharmony_ci        SampleDriverConfig {
725e41f4b71Sopenharmony_ci            sample_version = 1;
726e41f4b71Sopenharmony_ci            sample_bus = "I2C_0";
727e41f4b71Sopenharmony_ci            match_attr = "sample_config"; // The value must be the same as that of deviceMatchAttr in device_info.hcs.
728e41f4b71Sopenharmony_ci        }
729e41f4b71Sopenharmony_ci}
730e41f4b71Sopenharmony_ci    ```
731e41f4b71Sopenharmony_ci
732e41f4b71Sopenharmony_ci    Add the configuration file to the **hdf.hcs** file.
733e41f4b71Sopenharmony_ci
734e41f4b71Sopenharmony_ci    Example:
735e41f4b71Sopenharmony_ci
736e41f4b71Sopenharmony_ci    ```
737e41f4b71Sopenharmony_ci    #include "device_info/device_info.hcs"
738e41f4b71Sopenharmony_ci    #include "sample/sample_config.hcs"
739e41f4b71Sopenharmony_ci    ```
740e41f4b71Sopenharmony_ci
741e41f4b71Sopenharmony_ci### Driver Messaging Mechanism Development
742e41f4b71Sopenharmony_ci
743e41f4b71Sopenharmony_ci1.  Set the **policy** field in the driver configuration information to **2** (SERVICE_POLICY_CAPACITY). For details about the policy, see [Driver Service Management](#driver-service-management).
744e41f4b71Sopenharmony_ci
745e41f4b71Sopenharmony_ci    ```
746e41f4b71Sopenharmony_ci    device_sample :: Device {
747e41f4b71Sopenharmony_ci        policy = 2;
748e41f4b71Sopenharmony_ci        ...
749e41f4b71Sopenharmony_ci    }
750e41f4b71Sopenharmony_ci    ```
751e41f4b71Sopenharmony_ci
752e41f4b71Sopenharmony_ci2.  Set permissions for the device node of the driver. By default, the **permission** field is set to **0666**. You can set it based on service requirements.
753e41f4b71Sopenharmony_ci
754e41f4b71Sopenharmony_ci3.  Implement the **Dispatch()** method of **IDeviceIoService**.
755e41f4b71Sopenharmony_ci
756e41f4b71Sopenharmony_ci    ```c
757e41f4b71Sopenharmony_ci    // Dispatch() is used to process messages sent from the user-mode application.
758e41f4b71Sopenharmony_ci    int32_t SampleDriverDispatch(struct HdfDeviceIoClient *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
759e41f4b71Sopenharmony_ci    {
760e41f4b71Sopenharmony_ci        HDF_LOGI("sample driver lite A dispatch");
761e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
762e41f4b71Sopenharmony_ci    }
763e41f4b71Sopenharmony_ci    int32_t SampleDriverBind(struct HdfDeviceObject *device)
764e41f4b71Sopenharmony_ci    {
765e41f4b71Sopenharmony_ci        HDF_LOGI("test for lite os sample driver A Open!");
766e41f4b71Sopenharmony_ci        if (device == NULL) {
767e41f4b71Sopenharmony_ci            HDF_LOGE("test for lite os sample driver A Open failed!");
768e41f4b71Sopenharmony_ci            return HDF_FAILURE;
769e41f4b71Sopenharmony_ci        }
770e41f4b71Sopenharmony_ci        static struct ISampleDriverService sampleDriverA = {
771e41f4b71Sopenharmony_ci            .ioService.Dispatch = SampleDriverDispatch,
772e41f4b71Sopenharmony_ci            .ServiceA = SampleDriverServiceA,
773e41f4b71Sopenharmony_ci            .ServiceB = SampleDriverServiceB,
774e41f4b71Sopenharmony_ci        };
775e41f4b71Sopenharmony_ci        device->service = (struct IDeviceIoService *)(&sampleDriverA);
776e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
777e41f4b71Sopenharmony_ci    }
778e41f4b71Sopenharmony_ci    ```
779e41f4b71Sopenharmony_ci
780e41f4b71Sopenharmony_ci4.  Define the cmd type in the message processing function.
781e41f4b71Sopenharmony_ci
782e41f4b71Sopenharmony_ci    ```c
783e41f4b71Sopenharmony_ci    #define SAMPLE_WRITE_READ 1 // Read and write operation 1
784e41f4b71Sopenharmony_ci    ```
785e41f4b71Sopenharmony_ci
786e41f4b71Sopenharmony_ci5.  Enable the user-mode application to obtain a service and send a message to the driver.
787e41f4b71Sopenharmony_ci
788e41f4b71Sopenharmony_ci    ```c
789e41f4b71Sopenharmony_ci    int SendMsg(const char *testMsg)
790e41f4b71Sopenharmony_ci    {
791e41f4b71Sopenharmony_ci        if (testMsg == NULL) {
792e41f4b71Sopenharmony_ci            HDF_LOGE("test msg is null");
793e41f4b71Sopenharmony_ci            return HDF_FAILURE;
794e41f4b71Sopenharmony_ci        }
795e41f4b71Sopenharmony_ci        struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
796e41f4b71Sopenharmony_ci        if (serv == NULL) {
797e41f4b71Sopenharmony_ci            HDF_LOGE("fail to get service");
798e41f4b71Sopenharmony_ci            return HDF_FAILURE;
799e41f4b71Sopenharmony_ci        }
800e41f4b71Sopenharmony_ci        struct HdfSBuf *data = HdfSbufObtainDefaultSize();
801e41f4b71Sopenharmony_ci        if (data == NULL) {
802e41f4b71Sopenharmony_ci            HDF_LOGE("fail to obtain sbuf data");
803e41f4b71Sopenharmony_ci            return HDF_FAILURE;
804e41f4b71Sopenharmony_ci        }
805e41f4b71Sopenharmony_ci        struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
806e41f4b71Sopenharmony_ci        if (reply == NULL) {
807e41f4b71Sopenharmony_ci            HDF_LOGE("fail to obtain sbuf reply");
808e41f4b71Sopenharmony_ci            ret = HDF_DEV_ERR_NO_MEMORY;
809e41f4b71Sopenharmony_ci            goto out;
810e41f4b71Sopenharmony_ci        }
811e41f4b71Sopenharmony_ci        if (!HdfSbufWriteString(data, testMsg)) {
812e41f4b71Sopenharmony_ci            HDF_LOGE("fail to write sbuf");
813e41f4b71Sopenharmony_ci            ret = HDF_FAILURE;
814e41f4b71Sopenharmony_ci            goto out;
815e41f4b71Sopenharmony_ci        }
816e41f4b71Sopenharmony_ci        int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
817e41f4b71Sopenharmony_ci        if (ret != HDF_SUCCESS) {
818e41f4b71Sopenharmony_ci            HDF_LOGE("fail to send service call");
819e41f4b71Sopenharmony_ci            goto out;
820e41f4b71Sopenharmony_ci        }
821e41f4b71Sopenharmony_ci    out:
822e41f4b71Sopenharmony_ci        HdfSbufRecycle(data);
823e41f4b71Sopenharmony_ci        HdfSbbufRecycle(reply);
824e41f4b71Sopenharmony_ci        HdfIoServiceRecycle(serv);
825e41f4b71Sopenharmony_ci        return ret;
826e41f4b71Sopenharmony_ci    }
827e41f4b71Sopenharmony_ci    ```
828e41f4b71Sopenharmony_ci
829e41f4b71Sopenharmony_ci6.  Enable the user-mode process to receive messages from the driver.
830e41f4b71Sopenharmony_ci
831e41f4b71Sopenharmony_ci    1.  Implement the method for the user-mode application to process the events reported by the driver.
832e41f4b71Sopenharmony_ci
833e41f4b71Sopenharmony_ci        ```c
834e41f4b71Sopenharmony_ci        static int OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *data)
835e41f4b71Sopenharmony_ci        {
836e41f4b71Sopenharmony_ci            OsalTimespec time;
837e41f4b71Sopenharmony_ci            OsalGetTime(&time);
838e41f4b71Sopenharmony_ci            HDF_LOGI("%{public}s received event at %{public}llu.%{public}llu", (char *)priv, time.sec, time.usec);
839e41f4b71Sopenharmony_ci
840e41f4b71Sopenharmony_ci            const char *string = HdfSbufReadString(data);
841e41f4b71Sopenharmony_ci            if (string == NULL) {
842e41f4b71Sopenharmony_ci                HDF_LOGE("fail to read string in event data");
843e41f4b71Sopenharmony_ci                return HDF_FAILURE;
844e41f4b71Sopenharmony_ci            }
845e41f4b71Sopenharmony_ci            HDF_LOGI("%{public}s: dev event received: %{public}d %{public}s",  (char *)priv, id, string);
846e41f4b71Sopenharmony_ci            return HDF_SUCCESS;
847e41f4b71Sopenharmony_ci        }
848e41f4b71Sopenharmony_ci        ```
849e41f4b71Sopenharmony_ci
850e41f4b71Sopenharmony_ci    2.  Register the method for the user-mode application to receive messages from the driver.
851e41f4b71Sopenharmony_ci
852e41f4b71Sopenharmony_ci        ```c
853e41f4b71Sopenharmony_ci        int RegisterListen()
854e41f4b71Sopenharmony_ci        {
855e41f4b71Sopenharmony_ci            struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
856e41f4b71Sopenharmony_ci            if (serv == NULL) {
857e41f4b71Sopenharmony_ci                HDF_LOGE("fail to get service");
858e41f4b71Sopenharmony_ci                return HDF_FAILURE;
859e41f4b71Sopenharmony_ci            }
860e41f4b71Sopenharmony_ci            static struct HdfDevEventlistener listener = {
861e41f4b71Sopenharmony_ci                .callBack = OnDevEventReceived,
862e41f4b71Sopenharmony_ci                .priv ="Service0"
863e41f4b71Sopenharmony_ci            };
864e41f4b71Sopenharmony_ci            if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
865e41f4b71Sopenharmony_ci                HDF_LOGE("fail to register event listener");
866e41f4b71Sopenharmony_ci                return HDF_FAILURE;
867e41f4b71Sopenharmony_ci            }
868e41f4b71Sopenharmony_ci            ......
869e41f4b71Sopenharmony_ci            HdfDeviceUnregisterEventListener(serv, &listener);
870e41f4b71Sopenharmony_ci            HdfIoServiceRecycle(serv);
871e41f4b71Sopenharmony_ci            return HDF_SUCCESS;
872e41f4b71Sopenharmony_ci        }
873e41f4b71Sopenharmony_ci        ```
874e41f4b71Sopenharmony_ci
875e41f4b71Sopenharmony_ci    3.  Enable the driver to report events.
876e41f4b71Sopenharmony_ci
877e41f4b71Sopenharmony_ci        ```c
878e41f4b71Sopenharmony_ci        int32_t SampleDriverDispatch(HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
879e41f4b71Sopenharmony_ci        {
880e41f4b71Sopenharmony_ci            ... // process api call here
881e41f4b71Sopenharmony_ci            return HdfDeviceSendEvent(client->device, cmdCode, data);
882e41f4b71Sopenharmony_ci        }
883e41f4b71Sopenharmony_ci        ```
884e41f4b71Sopenharmony_ci
885e41f4b71Sopenharmony_ci### Driver Service Management Development
886e41f4b71Sopenharmony_ci
887e41f4b71Sopenharmony_ciThe development procedure is as follows:
888e41f4b71Sopenharmony_ci
889e41f4b71Sopenharmony_ci#### Defining the Services to be Published by the Driver
890e41f4b71Sopenharmony_ci
891e41f4b71Sopenharmony_ci```c
892e41f4b71Sopenharmony_ci// Define the driver service struct.
893e41f4b71Sopenharmony_cistruct ISampleDriverService {
894e41f4b71Sopenharmony_ci    struct IDeviceIoService ioService;       // The first member must be of the IDeviceIoService type.
895e41f4b71Sopenharmony_ci    int32_t (*ServiceA)(void);               // API of the first driver service.
896e41f4b71Sopenharmony_ci    int32_t (*ServiceB)(uint32_t inputCode); // API of the second driver service. You can add more as required.
897e41f4b71Sopenharmony_ci};
898e41f4b71Sopenharmony_ci
899e41f4b71Sopenharmony_ci// Implement the driver service APIs.
900e41f4b71Sopenharmony_ciint32_t SampleDriverServiceA(void)
901e41f4b71Sopenharmony_ci{
902e41f4b71Sopenharmony_ci    // You need to implement the service logic.
903e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
904e41f4b71Sopenharmony_ci}
905e41f4b71Sopenharmony_ci
906e41f4b71Sopenharmony_ciint32_t SampleDriverServiceB(uint32_t inputCode)
907e41f4b71Sopenharmony_ci{
908e41f4b71Sopenharmony_ci    // You need to implement the service logic.
909e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
910e41f4b71Sopenharmony_ci}
911e41f4b71Sopenharmony_ci```
912e41f4b71Sopenharmony_ci
913e41f4b71Sopenharmony_ci#### Binding Driver Services
914e41f4b71Sopenharmony_ci
915e41f4b71Sopenharmony_ciImplement the **Bind** pointer function, for example, **SampleDriverBind**, in **HdfDriverEntry** to bind the driver service to the HDF.
916e41f4b71Sopenharmony_ci
917e41f4b71Sopenharmony_ci```c
918e41f4b71Sopenharmony_ciint32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
919e41f4b71Sopenharmony_ci{
920e41f4b71Sopenharmony_ci    // deviceObject is a pointer to the device object created by the HDF for each driver. The device object holds private device data and service APIs.
921e41f4b71Sopenharmony_ci    if (deviceObject == NULL) {
922e41f4b71Sopenharmony_ci        HDF_LOGE("Sample device object is null!");
923e41f4b71Sopenharmony_ci        return HDF_FAILURE;
924e41f4b71Sopenharmony_ci    }
925e41f4b71Sopenharmony_ci    static struct ISampleDriverService sampleDriverA = {
926e41f4b71Sopenharmony_ci        .ServiceA = SampleDriverServiceA,
927e41f4b71Sopenharmony_ci        .ServiceB = SampleDriverServiceB,
928e41f4b71Sopenharmony_ci    };
929e41f4b71Sopenharmony_ci    deviceObject->service = &sampleDriverA.ioService;
930e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
931e41f4b71Sopenharmony_ci}
932e41f4b71Sopenharmony_ci```
933e41f4b71Sopenharmony_ci
934e41f4b71Sopenharmony_ci#### Obtaining Driver Services
935e41f4b71Sopenharmony_ci
936e41f4b71Sopenharmony_ciThe driver service can be obtained by using either of the following methods:
937e41f4b71Sopenharmony_ci
938e41f4b71Sopenharmony_ci##### Using the API provided by the HDF
939e41f4b71Sopenharmony_ci
940e41f4b71Sopenharmony_ciIf the service requester clearly knows when the driver is loaded, it can obtain the driver service by using the API provided by the HDF. The following is an example:
941e41f4b71Sopenharmony_ci
942e41f4b71Sopenharmony_ci```c
943e41f4b71Sopenharmony_ciconst struct ISampleDriverService *sampleService =
944e41f4b71Sopenharmony_ci        (const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
945e41f4b71Sopenharmony_ciif (sampleService == NULL) {
946e41f4b71Sopenharmony_ci    return HDF_FAILURE;
947e41f4b71Sopenharmony_ci}
948e41f4b71Sopenharmony_cisampleService->ServiceA();
949e41f4b71Sopenharmony_cisampleService->ServiceB(5);
950e41f4b71Sopenharmony_ci```
951e41f4b71Sopenharmony_ci
952e41f4b71Sopenharmony_ci##### Using the subscription mechanism
953e41f4b71Sopenharmony_ci
954e41f4b71Sopenharmony_ciIf the service requester is unaware of when the driver (in the same host) is loaded, it can use the subscription mechanism provided by the HDF to subscribe to the service. After the driver is loaded, the HDF publishes the driver service to the subscriber. The implementation is as follows:
955e41f4b71Sopenharmony_ci
956e41f4b71Sopenharmony_ci```c
957e41f4b71Sopenharmony_ci// Callback invoked to return the driver service after the subscribed driver is loaded.
958e41f4b71Sopenharmony_ci// object is the pointer to the private data of the subscriber, and service is the pointer to the subscribed service object.
959e41f4b71Sopenharmony_ciint32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
960e41f4b71Sopenharmony_ci{
961e41f4b71Sopenharmony_ci    const struct ISampleDriverService *sampleService =
962e41f4b71Sopenharmony_ci        (const struct ISampleDriverService *)service;
963e41f4b71Sopenharmony_ci    if (sampleService == NULL) {
964e41f4b71Sopenharmony_ci        return HDF_FAILURE;
965e41f4b71Sopenharmony_ci    }
966e41f4b71Sopenharmony_ci    sampleService->ServiceA();
967e41f4b71Sopenharmony_ci    sampleService->ServiceB(5);
968e41f4b71Sopenharmony_ci}
969e41f4b71Sopenharmony_ci// Implement the subscription process.
970e41f4b71Sopenharmony_ciint32_t TestDriverInit(struct HdfDeviceObject *deviceObject)
971e41f4b71Sopenharmony_ci{
972e41f4b71Sopenharmony_ci    if (deviceObject == NULL) {
973e41f4b71Sopenharmony_ci        HDF_LOGE("Test driver init failed, deviceObject is null!");
974e41f4b71Sopenharmony_ci        return HDF_FAILURE;
975e41f4b71Sopenharmony_ci    }
976e41f4b71Sopenharmony_ci    struct SubscriberCallback callBack;
977e41f4b71Sopenharmony_ci    callBack.deviceObject = deviceObject;
978e41f4b71Sopenharmony_ci    callBack.OnServiceConnected = TestDriverSubCallBack;
979e41f4b71Sopenharmony_ci    int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
980e41f4b71Sopenharmony_ci    if (ret != HDF_SUCCESS) {
981e41f4b71Sopenharmony_ci        HDF_LOGE("Test driver subscribe sample driver failed!");
982e41f4b71Sopenharmony_ci    }
983e41f4b71Sopenharmony_ci    return ret;
984e41f4b71Sopenharmony_ci}
985e41f4b71Sopenharmony_ci```
986e41f4b71Sopenharmony_ci
987e41f4b71Sopenharmony_ci## HDF Development Example
988e41f4b71Sopenharmony_ci
989e41f4b71Sopenharmony_ciThe following is a HDF-based driver development example.
990e41f4b71Sopenharmony_ci
991e41f4b71Sopenharmony_ci### Adding the Driver Configuration
992e41f4b71Sopenharmony_ci
993e41f4b71Sopenharmony_ciAdd the driver configuration to the HDF configuration file, for example, **vendor/hisilicon/xxx/hdf_config/device_info**.
994e41f4b71Sopenharmony_ci
995e41f4b71Sopenharmony_ci```
996e41f4b71Sopenharmony_ciroot {
997e41f4b71Sopenharmony_ci    device_info {
998e41f4b71Sopenharmony_ci        match_attr = "hdf_manager";
999e41f4b71Sopenharmony_ci        template host {
1000e41f4b71Sopenharmony_ci            hostName = "";
1001e41f4b71Sopenharmony_ci            priority = 100;
1002e41f4b71Sopenharmony_ci            template device {
1003e41f4b71Sopenharmony_ci                template deviceNode {
1004e41f4b71Sopenharmony_ci                    policy = 0;
1005e41f4b71Sopenharmony_ci                    priority = 100;
1006e41f4b71Sopenharmony_ci                    preload = 0;
1007e41f4b71Sopenharmony_ci                    permission = 0664;
1008e41f4b71Sopenharmony_ci                    moduleName = "";
1009e41f4b71Sopenharmony_ci                    serviceName = "";
1010e41f4b71Sopenharmony_ci                    deviceMatchAttr = "";
1011e41f4b71Sopenharmony_ci                }
1012e41f4b71Sopenharmony_ci            }
1013e41f4b71Sopenharmony_ci        }
1014e41f4b71Sopenharmony_ci        sample_host :: host {
1015e41f4b71Sopenharmony_ci            hostName = "sample_host";
1016e41f4b71Sopenharmony_ci            sample_device :: device {
1017e41f4b71Sopenharmony_ci                device0 :: deviceNode {
1018e41f4b71Sopenharmony_ci                    policy = 2;
1019e41f4b71Sopenharmony_ci                    priority = 100;
1020e41f4b71Sopenharmony_ci                    preload = 1;
1021e41f4b71Sopenharmony_ci                    permission = 0664;
1022e41f4b71Sopenharmony_ci                    moduleName = "sample_driver";
1023e41f4b71Sopenharmony_ci                    serviceName = "sample_service";
1024e41f4b71Sopenharmony_ci                }
1025e41f4b71Sopenharmony_ci            }
1026e41f4b71Sopenharmony_ci        }
1027e41f4b71Sopenharmony_ci    }
1028e41f4b71Sopenharmony_ci}
1029e41f4b71Sopenharmony_ci```
1030e41f4b71Sopenharmony_ci
1031e41f4b71Sopenharmony_ci### Writing the Driver Code
1032e41f4b71Sopenharmony_ci
1033e41f4b71Sopenharmony_ciThe sample driver code compiled based on the HDF framework is as follows:
1034e41f4b71Sopenharmony_ci
1035e41f4b71Sopenharmony_ci```c
1036e41f4b71Sopenharmony_ci#include <fcntl.h>
1037e41f4b71Sopenharmony_ci#include <sys/stat.h>
1038e41f4b71Sopenharmony_ci#include <sys/ioctl.h>
1039e41f4b71Sopenharmony_ci#include "hdf_log.h"
1040e41f4b71Sopenharmony_ci#include "hdf_base.h"
1041e41f4b71Sopenharmony_ci#include "hdf_device_desc.h"
1042e41f4b71Sopenharmony_ci
1043e41f4b71Sopenharmony_ci#define HDF_LOG_TAG sample_driver
1044e41f4b71Sopenharmony_ci
1045e41f4b71Sopenharmony_ci#define SAMPLE_WRITE_READ 123
1046e41f4b71Sopenharmony_ci
1047e41f4b71Sopenharmony_cistatic int32_t HdfSampleDriverDispatch(
1048e41f4b71Sopenharmony_ci    struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
1049e41f4b71Sopenharmony_ci{
1050e41f4b71Sopenharmony_ci    HDF_LOGI("%{public}s: received cmd %{public}d", __func__, id);
1051e41f4b71Sopenharmony_ci    if (id == SAMPLE_WRITE_READ) {
1052e41f4b71Sopenharmony_ci        const char *readData = HdfSbufReadString(data);
1053e41f4b71Sopenharmony_ci        if (readData != NULL) {
1054e41f4b71Sopenharmony_ci            HDF_LOGE("%{public}s: read data is: %{public}s", __func__, readData);
1055e41f4b71Sopenharmony_ci        }
1056e41f4b71Sopenharmony_ci        if (!HdfSbufWriteInt32(reply, INT32_MAX)) {
1057e41f4b71Sopenharmony_ci            HDF_LOGE("%{public}s: reply int32 fail", __func__);
1058e41f4b71Sopenharmony_ci        }
1059e41f4b71Sopenharmony_ci        return HdfDeviceSendEvent(client->device, id, data);
1060e41f4b71Sopenharmony_ci    }
1061e41f4b71Sopenharmony_ci    return HDF_FAILURE;
1062e41f4b71Sopenharmony_ci}
1063e41f4b71Sopenharmony_ci
1064e41f4b71Sopenharmony_cistatic void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
1065e41f4b71Sopenharmony_ci{
1066e41f4b71Sopenharmony_ci    // Release resources here
1067e41f4b71Sopenharmony_ci    return;
1068e41f4b71Sopenharmony_ci}
1069e41f4b71Sopenharmony_ci
1070e41f4b71Sopenharmony_cistatic int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
1071e41f4b71Sopenharmony_ci{
1072e41f4b71Sopenharmony_ci    if (deviceObject == NULL) {
1073e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1074e41f4b71Sopenharmony_ci    }
1075e41f4b71Sopenharmony_ci    static struct IDeviceIoService testService = {
1076e41f4b71Sopenharmony_ci        .Dispatch = HdfSampleDriverDispatch,
1077e41f4b71Sopenharmony_ci    };
1078e41f4b71Sopenharmony_ci    deviceObject->service = &testService;
1079e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1080e41f4b71Sopenharmony_ci}
1081e41f4b71Sopenharmony_ci
1082e41f4b71Sopenharmony_cistatic int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
1083e41f4b71Sopenharmony_ci{
1084e41f4b71Sopenharmony_ci    if (deviceObject == NULL) {
1085e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s::ptr is null!", __func__);
1086e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1087e41f4b71Sopenharmony_ci    }
1088e41f4b71Sopenharmony_ci    HDF_LOGI("Sample driver Init success");
1089e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1090e41f4b71Sopenharmony_ci}
1091e41f4b71Sopenharmony_ci
1092e41f4b71Sopenharmony_cistatic struct HdfDriverEntry g_sampleDriverEntry = {
1093e41f4b71Sopenharmony_ci    .moduleVersion = 1,
1094e41f4b71Sopenharmony_ci    .moduleName = "sample_driver",
1095e41f4b71Sopenharmony_ci    .Bind = HdfSampleDriverBind,
1096e41f4b71Sopenharmony_ci    .Init = HdfSampleDriverInit,
1097e41f4b71Sopenharmony_ci    .Release = HdfSampleDriverRelease,
1098e41f4b71Sopenharmony_ci};
1099e41f4b71Sopenharmony_ci
1100e41f4b71Sopenharmony_ciHDF_INIT(g_sampleDriverEntry);
1101e41f4b71Sopenharmony_ci```
1102e41f4b71Sopenharmony_ci
1103e41f4b71Sopenharmony_ci### Implementing Interaction Between the Application and the Driver
1104e41f4b71Sopenharmony_ci
1105e41f4b71Sopenharmony_ciWrite the code for interaction between the user-mode application and the driver. Place the code in the **drivers/hdf_core/adapter/uhdf** directory for compilation. For details about **BUILD.gn**, see **drivers/hdf_core/framework/sample/platform/uart/dev/BUILD.gn**.
1106e41f4b71Sopenharmony_ci
1107e41f4b71Sopenharmony_ci```c
1108e41f4b71Sopenharmony_ci#include <fcntl.h>
1109e41f4b71Sopenharmony_ci#include <sys/stat.h>
1110e41f4b71Sopenharmony_ci#include <sys/ioctl.h>
1111e41f4b71Sopenharmony_ci#include <unistd.h>
1112e41f4b71Sopenharmony_ci#include "hdf_log.h"
1113e41f4b71Sopenharmony_ci#include "hdf_sbuf.h"
1114e41f4b71Sopenharmony_ci#include "hdf_io_service_if.h"
1115e41f4b71Sopenharmony_ci
1116e41f4b71Sopenharmony_ci#define HDF_LOG_TAG sample_test
1117e41f4b71Sopenharmony_ci#define SAMPLE_SERVICE_NAME "sample_service"
1118e41f4b71Sopenharmony_ci
1119e41f4b71Sopenharmony_ci#define SAMPLE_WRITE_READ 123
1120e41f4b71Sopenharmony_ci
1121e41f4b71Sopenharmony_ciint g_replyFlag = 0;
1122e41f4b71Sopenharmony_ci
1123e41f4b71Sopenharmony_cistatic int OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *data)
1124e41f4b71Sopenharmony_ci{
1125e41f4b71Sopenharmony_ci    const char *string = HdfSbufReadString(data);
1126e41f4b71Sopenharmony_ci    if (string == NULL) {
1127e41f4b71Sopenharmony_ci        HDF_LOGE("fail to read string in event data");
1128e41f4b71Sopenharmony_ci        g_replyFlag = 1;
1129e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1130e41f4b71Sopenharmony_ci    }
1131e41f4b71Sopenharmony_ci    HDF_LOGI("%{public}s: dev event received: %{public}u %{public}s",  (char *)priv, id, string);
1132e41f4b71Sopenharmony_ci    g_replyFlag = 1;
1133e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1134e41f4b71Sopenharmony_ci}
1135e41f4b71Sopenharmony_ci
1136e41f4b71Sopenharmony_cistatic int SendEvent(struct HdfIoService *serv, char *eventData)
1137e41f4b71Sopenharmony_ci{
1138e41f4b71Sopenharmony_ci    int ret = 0;
1139e41f4b71Sopenharmony_ci    struct HdfSBuf *data = HdfSbufObtainDefaultSize();
1140e41f4b71Sopenharmony_ci    if (data == NULL) {
1141e41f4b71Sopenharmony_ci        HDF_LOGE("fail to obtain sbuf data");
1142e41f4b71Sopenharmony_ci        return 1;
1143e41f4b71Sopenharmony_ci    }
1144e41f4b71Sopenharmony_ci
1145e41f4b71Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
1146e41f4b71Sopenharmony_ci    if (reply == NULL) {
1147e41f4b71Sopenharmony_ci        HDF_LOGE("fail to obtain sbuf reply");
1148e41f4b71Sopenharmony_ci        ret = HDF_DEV_ERR_NO_MEMORY;
1149e41f4b71Sopenharmony_ci        goto out;
1150e41f4b71Sopenharmony_ci    }
1151e41f4b71Sopenharmony_ci
1152e41f4b71Sopenharmony_ci    if (!HdfSbufWriteString(data, eventData)) {
1153e41f4b71Sopenharmony_ci        HDF_LOGE("fail to write sbuf");
1154e41f4b71Sopenharmony_ci        ret = HDF_FAILURE;
1155e41f4b71Sopenharmony_ci        goto out;
1156e41f4b71Sopenharmony_ci    }
1157e41f4b71Sopenharmony_ci
1158e41f4b71Sopenharmony_ci    ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
1159e41f4b71Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1160e41f4b71Sopenharmony_ci        HDF_LOGE("fail to send service call");
1161e41f4b71Sopenharmony_ci        goto out;
1162e41f4b71Sopenharmony_ci    }
1163e41f4b71Sopenharmony_ci
1164e41f4b71Sopenharmony_ci    int replyData = 0;
1165e41f4b71Sopenharmony_ci    if (!HdfSbufReadInt32(reply, &replyData)) {
1166e41f4b71Sopenharmony_ci        HDF_LOGE("fail to get service call reply");
1167e41f4b71Sopenharmony_ci        ret = HDF_ERR_INVALID_OBJECT;
1168e41f4b71Sopenharmony_ci        goto out;
1169e41f4b71Sopenharmony_ci    }
1170e41f4b71Sopenharmony_ci    HDF_LOGI("Get reply is: %{public}d", replyData);
1171e41f4b71Sopenharmony_ciout:
1172e41f4b71Sopenharmony_ci    HdfSbufRecycle(data);
1173e41f4b71Sopenharmony_ci    HdfSbufRecycle(reply);
1174e41f4b71Sopenharmony_ci    return ret;
1175e41f4b71Sopenharmony_ci}
1176e41f4b71Sopenharmony_ci
1177e41f4b71Sopenharmony_ciint main()
1178e41f4b71Sopenharmony_ci{
1179e41f4b71Sopenharmony_ci    char *sendData = "default event info";
1180e41f4b71Sopenharmony_ci    struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);
1181e41f4b71Sopenharmony_ci    if (serv == NULL) {
1182e41f4b71Sopenharmony_ci        HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
1183e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1184e41f4b71Sopenharmony_ci    }
1185e41f4b71Sopenharmony_ci
1186e41f4b71Sopenharmony_ci    static struct HdfDevEventlistener listener = {
1187e41f4b71Sopenharmony_ci        .callBack = OnDevEventReceived,
1188e41f4b71Sopenharmony_ci        .priv ="Service0"
1189e41f4b71Sopenharmony_ci    };
1190e41f4b71Sopenharmony_ci
1191e41f4b71Sopenharmony_ci    if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) {
1192e41f4b71Sopenharmony_ci        HDF_LOGE("fail to register event listener");
1193e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1194e41f4b71Sopenharmony_ci    }
1195e41f4b71Sopenharmony_ci    if (SendEvent(serv, sendData)) {
1196e41f4b71Sopenharmony_ci        HDF_LOGE("fail to send event");
1197e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1198e41f4b71Sopenharmony_ci    }
1199e41f4b71Sopenharmony_ci
1200e41f4b71Sopenharmony_ci    while (g_replyFlag == 0) {
1201e41f4b71Sopenharmony_ci        sleep(1);
1202e41f4b71Sopenharmony_ci    }
1203e41f4b71Sopenharmony_ci
1204e41f4b71Sopenharmony_ci    if (HdfDeviceUnregisterEventListener(serv, &listener)) {
1205e41f4b71Sopenharmony_ci        HDF_LOGE("fail to  unregister listener");
1206e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1207e41f4b71Sopenharmony_ci    }
1208e41f4b71Sopenharmony_ci
1209e41f4b71Sopenharmony_ci    HdfIoServiceRecycle(serv);
1210e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1211e41f4b71Sopenharmony_ci}
1212e41f4b71Sopenharmony_ci```
1213e41f4b71Sopenharmony_ci
1214e41f4b71Sopenharmony_ci>   **NOTE**
1215e41f4b71Sopenharmony_ci>
1216e41f4b71Sopenharmony_ci>   The user-mode application uses the message sending API of the HDF, and the compilation of the user-mode application depends on the dynamic libraries **hdf_core** and **osal** provided by the HDF. Therefore, you need to add the following dependencies to the .gn file:
1217e41f4b71Sopenharmony_ci>
1218e41f4b71Sopenharmony_ci>   deps = [
1219e41f4b71Sopenharmony_ci>
1220e41f4b71Sopenharmony_ci>   ​        "//drivers/hdf_core/adapter/uhdf/manager:hdf_core",
1221e41f4b71Sopenharmony_ci>
1222e41f4b71Sopenharmony_ci>   ​        "//drivers/hdf_core/adapter/uhdf/posix:hdf_posix_osal",
1223e41f4b71Sopenharmony_ci>
1224e41f4b71Sopenharmony_ci>   ]
1225