• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Driver Development
2
3
4## Driver Model
5
6The Hardware Driver Foundation (HDF) is designed based on a modular driver model to enable refined driver management and streamline driver development and deployment. The HDF allows the same type of device drivers to be placed in a host. The host manages the start and loading of a group of devices. You can deploy dependent drivers to the same host, and deploy independent drivers to different hosts.
7
8The figure below shows the HDF driver model. A device refers to a physical device. A DeviceNode is a component of a device. A device has at least one DeviceNode. Each DeviceNode can publish a device service. Each DevicdNode has a unique driver to interact with the hardware.
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, write of the driver compilation script, and driver configuration. The procedure is as follows:
18
191. Implement a driver.
20
21   Write the driver code and register the driver entry with the HDF.
22
23   - Write the driver service code. <br>The following is an example:
24
25      ```c
26      #include "hdf_device_desc.h"          // Header file that defines the driver development APIs provided by the HDF.
27      #include "hdf_log.h"                  // Header file that defines the log APIs provided by the HDF.
28
29      #define HDF_LOG_TAG "sample_driver"   // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
30
31      // Bind the service APIs provided by the driver to the HDF.
32      int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
33      {
34          HDF_LOGD("Sample driver bind success");
35          return HDF_SUCCESS;
36      }
37
38      // Initialize the driver service.
39      int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
40      {
41          HDF_LOGD("Sample driver Init success");
42          return HDF_SUCCESS;
43      }
44
45      // Release the driver resources.
46      void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
47      {
48          HDF_LOGD("Sample driver release success");
49          return;
50      }
51      ```
52   - Register the driver entry with the HDF.
53
54      ```c
55      // Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h).
56      struct HdfDriverEntry g_sampleDriverEntry = {
57          .moduleVersion = 1,
58          .moduleName = "sample_driver",
59          .Bind = HdfSampleDriverBind,
60          .Init = HdfSampleDriverInit,
61          .Release = HdfSampleDriverRelease,
62      };
63
64      // 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.
65      HDF_INIT(g_sampleDriverEntry);
66      ```
67
682. Write the driver compilation script.
69
70   - LiteOS
71
72     Modify **makefile** and **BUILD.gn** files.
73
74     - **Makefile**:
75
76       Use the **makefile** template provided by the HDF to compile the driver code.
77
78
79       ```c
80       include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # (Mandatory) Import the HDF predefined content.
81       MODULE_NAME :=        # File to be generated.
82       LOCAL_INCLUDE: =      # Directory of the driver header files.
83       LOCAL_SRCS : =        # Source code files of the driver.
84       LOCAL_CFLAGS : =      # Custom build options.
85       include $(HDF_DRIVER) # Import the makefile template to complete the build.
86       ```
87
88       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. <br>The following is an example:
89
90
91       ```c
92       LITEOS_BASELIB += -lxxx # Static library generated by the link.
93       LIB_SUBDIRS    +=         # Directory in which makefile is located.
94       ```
95
96     - **BUILD.gn**:
97
98       Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
99
100
101       ```c
102       import("//build/lite/config/component/lite_component.gni")
103       import("//drivers/hdf_core/adapter/khdf/liteos/hdf.gni")
104       module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
105       module_name = "xxx"
106       hdf_driver(module_name) {
107           sources = [
108               "xxx/xxx/xxx.c",           # Source code to compile.
109           ]
110           public_configs = [ ":public" ] # Head file configuration of the dependencies.
111       }
112       config("public") {                 # Define the head file configuration of the dependencies.
113           include_dirs = [
114               "xxx/xxx/xxx",             # Directory of dependency header files.
115           ]
116       }
117       ```
118
119       Add the **BUILD.gn** directory to **/drivers/hdf_core/adapter/khdf/liteos/BUILD.gn**.
120
121
122       ```c
123       group("liteos") {
124           public_deps = [ ":$module_name" ]
125               deps = [
126                   "xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/hdf_core/adapter/khdf/liteos.
127               ]
128       }
129       ```
130   - Linux
131
132     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**.
133
134
135     ```c
136     source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
137     ```
138
139     Add the driver directory to **drivers/hdf_core/adapter/khdf/linux/Makefile**.
140
141
142     ```c
143     obj-$(CONFIG_DRIVERS_HDF)  += xxx/
144     ```
145
146     Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
147
148
149     ```c
150     obj-y  += xxx.o
151     ```
152
1533. Configure the driver.
154
155   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).
156
157   The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
158
159   - (Mandatory) Set driver device information.
160
161     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. <br>The following is an example:
162
163
164      ```
165      root {
166          device_info {
167              match_attr = "hdf_manager";
168              template host {       // Host template. If a node (for example, sample_host) uses the default values in this template, the node fields can be omitted.
169                  hostName = "";
170                  priority = 100;
171                  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.
172                  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.
173                  caps = [""]];     // Linux capabilities of the user-mode process. It is left empty by default. Set this parameter based on service requirements.
174                  template device {
175                      template deviceNode {
176                          policy = 0;
177                          priority = 100;
178                          preload = 0;
179                          permission = 0664;
180                          moduleName = "";
181                          serviceName = "";
182                          deviceMatchAttr = "";
183                      }
184                  }
185              }
186              sample_host :: host{
187                  hostName = "host0";    // Host name. The host node is used as a container to hold a type of drivers.
188                  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.
189                  caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"];   // Linux capabilities of a user-mode process.
190                  device_sample :: device {        // Sample device node.
191                      device0 :: deviceNode {      // DeviceNode of the sample driver.
192                          policy = 1;              // Policy for publishing the driver service. For details, see Driver Service Management.
193                          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.
194                          preload = 0;             // The value 0 means to load the driver by default during the startup of the system.
195                          permission = 0664;       // Permission for the DeviceNode created.
196                          moduleName = "sample_driver";      // Driver name. The value must be the same as that of moduleName in the HdfDriverEntry structure.
197                          serviceName = "sample_service";    // Name of the service published by the driver. The service name must be unique.
198                          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.
199                      }
200                  }
201              }
202          }
203      }
204      ```
205
206      > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/>
207      >
208      > - **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
209      >
210      > - 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.
211      >
212      > - If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
213      >
214      > - 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/wikis).
215      >
216      > - 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"]**.
217      >
218      > - **preload** specifies the driver loading policy. For details, see [Driver Loading](../driver/driver-hdf-load.md).
219
220
221   - (Optional) Set driver private information.
222
223     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). <br>The following is an example of the driver configuration:
224
225
226      ```
227      root {
228          SampleDriverConfig {
229              sample_version = 1;
230              sample_bus = "I2C_0";
231              match_attr = "sample_config"; // The value must be the same as that of deviceMatchAttr in device_info.hcs.
232          }
233      }
234      ```
235
236      Add the configuration file to the **hdf.hcs** file. <br>The following is an example:
237
238
239      ```
240      #include "device_info/device_info.hcs"
241      #include "sample/sample_config.hcs"
242      ```
243