• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Driver Development
2
3
4## Driver Model
5
6The Hardware Driver Foundation (HDF) is designed upon a component-based driver model. This model enables refined driver management and streamlines driver development and deployment. In the HDF, the same type of device drivers are placed in a host. You can develop and deploy the drivers separately. One driver can have multiple nodes.
7
8The figure below shows the HDF driver model.
9
10  **Figure 1** HDF driver model
11
12  ![](figures/hdf-driver-model.png)
13
14
15## How to Develop
16
17The HDF-based driver development involves driver implementation and configuration. The procedure is as follows:
18
191. Implement a driver.<br/>
20   Write the driver code and register the driver entry with the HDF.
21
22   - Writing the driver service code
23
24     The following is an example:
25
26   ```
27   #include "hdf_device_desc.h"  // Header file that defines the driver development APIs provided by the HDF.
28   #include "hdf_log.h"          // Header file that defines the log APIs provided by the HDF.
29
30   #define HDF_LOG_TAG "sample_driver"   // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
31
32   // Bind the service interface provided by the driver to the HDF.
33   int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
34   {
35       HDF_LOGD("Sample driver bind success");
36       return 0;
37   }
38
39   // Initialize the driver service.
40   int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
41   {
42       HDF_LOGD("Sample driver Init success");
43       return 0;
44   }
45
46   // Release the driver resources.
47   void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
48   {
49       HDF_LOGD("Sample driver release success");
50       return;
51   }
52   ```
53
54   - Registering the driver entry with the HDF
55
56
57   ```
58   // Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h).
59   struct HdfDriverEntry g_sampleDriverEntry = {
60       .moduleVersion = 1,
61       .moduleName = "sample_driver",
62       .Bind = HdfSampleDriverBind,
63       .Init = HdfSampleDriverInit,
64       .Release = HdfSampleDriverRelease,
65   };
66
67   // Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
68   HDF_INIT(g_sampleDriverEntry);
69   ```
70
712. Build the driver.<br/>
72   - LiteOS<br/>
73      Modify **makefile** and **BUILD.gn**.
74
75      - **makefile**:<br/>
76         Use the **makefile** template provided by the HDF to compile the driver code.
77
78
79         ```
80         include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory.
81         MODULE_NAME :=    # File to be generated.
82         LOCAL_INCLUDE: =  # Directory of the driver header files.
83         LOCAL_SRCS : =     # Source code file of the driver.
84         LOCAL_CFLAGS : =  # Custom compilation options.
85         include $(HDF_DRIVER) # Import the makefile template to complete the compilation.
86         ```
87
88         Add the path of the generated file to **hdf_lite.mk** in the **drivers/adapter/khdf/liteos** directory to link the file to the kernel image.
89
90
91         ```
92         LITEOS_BASELIB += -lxxx # Static library generated by the link.
93         LIB_SUBDIRS    +=         # Directory in which the driver code makefile is located.
94         ```
95
96      - **BUILD.gn**:<br/>
97         Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
98
99
100         ```
101         import("//build/lite/config/component/lite_component.gni")
102         import("//drivers/adapter/khdf/liteos/hdf.gni")
103         module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
104         module_name = "xxx"
105         hdf_driver(module_name) {
106             sources = [
107                 "xxx/xxx/xxx.c", # Source code to compile.
108             ]
109             public_configs = [ ":public" ] # Head file configuration of the dependencies.
110         }
111         config("public") {# Define the head file configuration of the dependencies.
112             include_dirs = [
113             "xxx/xxx/xxx", # Directory of the dependency header files.
114             ]
115         }
116         ```
117
118         Add the **BUILD.gn** directory to **/drivers/adapter/khdf/liteos/BUILD.gn**.
119
120
121         ```
122         group("liteos") {
123                public_deps = [ ":$module_name" ]
124                    deps = [
125                       "xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos.
126                   ]
127         }
128         ```
129   - Linux<br/>
130      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/adapter/khdf/linux/Kconfig**.
131
132
133      ```
134      source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
135      ```
136
137      Add the driver directory to **drivers/adapter/khdf/linux/Makefile**.
138
139
140      ```
141      obj-$(CONFIG_DRIVERS_HDF)  += xxx/
142      ```
143
144      Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
145
146
147      ```
148      obj-y  += xxx.o
149      ```
150
1513. Configure the driver.<br/>
152   The HDF Configuration Source (HCS) contains the source code of HDF configuration. For details about the HCS, see [Configuration Management](../driver/driver-hdf-manage.md).
153
154   The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
155
156   - (Mandatory) Setting the driver device description<br/>
157      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. The following is an example:
158
159
160      ```
161      root {
162          device_info {
163              match_attr = "hdf_manager";
164              template host {       // Host template. If a node (for example, sample_host) uses the default values in this template, the node fields can be omitted.
165                  hostName = "";
166                  priority = 100;
167                  uid = "";        // User ID (UID) of a 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.
168                  gid = "";        // Group ID (GID) of a 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.
169                  caps = [""]];     // Linux capabilities of a user-mode process. It is left empty by default. Set this parameter based on service requirements.
170                  template device {
171                      template deviceNode {
172                          policy = 0;
173                          priority = 100;
174                          preload = 0;
175                          permission = 0664;
176                          moduleName = "";
177                          serviceName = "";
178                          deviceMatchAttr = "";
179                      }
180                  }
181              }
182              sample_host :: host{
183                  hostName = "host0";    // Host name. The host node is used as a container to hold a type of drivers.
184                  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.
185                  caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"];   // Linux capabilities of the user-mode process.
186                  device_sample :: device {        // Sample device node.
187                      device0 :: deviceNode {      // DeviceNode of the sample driver.
188                          policy = 1;             // Policy for providing the driver service. For details, see Driver Service Management.
189                          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.
190                          preload = 0;            // The loading mode of the driver is on-demand loading. For details, see "NOTE" at the end of this document.
191                          permission = 0664;       // Permission for the driver to create a device node.
192                          moduleName = "sample_driver"; // Driver name. The value must be the same as that of moduleName in the HdfDriverEntry structure.
193                          serviceName = "sample_service";    // Name of the service provided by the driver. The service name must be unique.
194                          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.
195                      }
196                  }
197              }
198          }
199      }
200      ```
201      ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**<br>
202
203      - **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
204      - 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.
205      - If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
206      - The process UIDs are configured in **base/startup/init_lite/services/etc/passwd**, and the process GIDs are configured in **base/startup/init_lite/services/etc/group**. For details, see [Adding a System Service User Group]( https://gitee.com/openharmony/startup_init_lite/wikis).
207      - If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
208
209
210
211   - (Optional) Setting driver private information<br/>
212      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 step 1).
213
214      The following is an example of the driver private configuration:
215
216
217      ```
218      root {
219          SampleDriverConfig {
220              sample_version = 1;
221              sample_bus = "I2C_0";
222              match_attr = "sample_config"; // The value must be the same as that of deviceMatchAttr in device_info.hcs.
223          }
224      }
225      ```
226
227      After the configuration, add the configuration file to the board-level configuration entry file **hdf.hcs**. (You can use DevEco to perform one-click configuration. For details, see the description about the driver development suite.)
228
229      The following is an example:
230
231
232      ```
233      #include "device_info/device_info.hcs"
234      #include "sample/sample_config.hcs"
235      ```
236
237
238> ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**<br>
239> Drivers can be loaded on demand or in sequence.
240>
241> - On-demand loading
242>
243>   ```
244>   typedef enum {
245>       DEVICE_PRELOAD_ENABLE = 0,
246>       DEVICE_PRELOAD_ENABLE_STEP2,
247>       DEVICE_PRELOAD_DISABLE,
248>       DEVICE_PRELOAD_INVALID
249>   } DevicePreload;
250>   ```
251>
252>   If **preload** in the configuration file is set to **0 (DEVICE_PRELOAD_ENABLE)**, the driver is loaded by default during the system boot process.
253>
254>   If **preload** is set to **1 (DEVICE_PRELOAD_ENABLE_STEP2)**, the driver is loaded 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**.
255>
256>   If **preload** is set to **2 (DEVICE_PRELOAD_DISABLE)** , the driver is dynamically loaded instead of being 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.  For more details, see [Driver Messaging Mechanism](driver-hdf-message-management.md).
257>
258> - Sequential loading (**preload** set to **0 (DEVICE_PRELOAD_ENABLE)**)<br/>
259>   In the configuration file, the **priority** fields (value range: 0 to 200) determines the loading sequence of a host and a driver. For drivers in different hosts, a smaller host priority value indicates a higher driver loading priority; for drivers in the same host, a smaller driver priority value indicates a higher driver loading priority.
260