driver-hdf-development.md 11.7 KB
Newer Older
A
annie_wangli 已提交
1 2 3 4 5
# Driver Development


## Driver Model

6
The 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.
A
Annie_wang 已提交
7

8
The 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.
A
Annie_wang 已提交
9

A
Annie_wang 已提交
10
  **Figure 1** HDF driver model
A
annie_wangli 已提交
11 12 13 14

  ![](figures/hdf-driver-model.png)


15
## How to Develop
A
annie_wangli 已提交
16

17
The HDF-based driver development involves driver implementation, write of the driver compilation script, and driver configuration. The procedure is as follows:
A
annie_wangli 已提交
18

A
Annie_wang 已提交
19
1. Implement a driver.
A
Annie_wang 已提交
20

A
Annie_wang 已提交
21
   Write the driver code and register the driver entry with the HDF.
A
Annie_wang 已提交
22

23
   - Write the driver service code. <br>The following is an example:
A
Annie_wang 已提交
24
     
25
      ```c
A
Annie_wang 已提交
26 27
      #include "hdf_device_desc.h"          // Header file that defines the driver development APIs provided by the HDF.
      #include "hdf_log.h"                  // Header file that defines the log APIs provided by the HDF.
A
Annie_wang 已提交
28 29 30
      
      #define HDF_LOG_TAG "sample_driver"   // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
      
A
Annie_wang 已提交
31
      // Bind the service APIs provided by the driver to the HDF.
A
Annie_wang 已提交
32 33 34
      int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
      {
          HDF_LOGD("Sample driver bind success");
35
          return HDF_SUCCESS;
A
Annie_wang 已提交
36 37 38 39 40 41
      }
      
      // Initialize the driver service.
      int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
      {
          HDF_LOGD("Sample driver Init success");
42
          return HDF_SUCCESS;
A
Annie_wang 已提交
43 44 45 46 47 48 49 50 51
      }
      
      // Release the driver resources.
      void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
      {
          HDF_LOGD("Sample driver release success");
          return;
      }
      ```
A
Annie_wang 已提交
52
   - Register the driver entry with the HDF.
A
Annie_wang 已提交
53
     
54
      ```c
A
Annie_wang 已提交
55 56 57 58 59 60 61 62 63
      // Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h). 
      struct HdfDriverEntry g_sampleDriverEntry = {
          .moduleVersion = 1,
          .moduleName = "sample_driver",
          .Bind = HdfSampleDriverBind,
          .Init = HdfSampleDriverInit,
          .Release = HdfSampleDriverRelease,
      };
      
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.
A
Annie_wang 已提交
65 66
      HDF_INIT(g_sampleDriverEntry);
      ```
A
Annie_wang 已提交
67

68
2. Write the driver compilation script.
A
Annie_wang 已提交
69

A
Annie_wang 已提交
70
   - LiteOS
A
Annie_wang 已提交
71

72
     Modify **makefile** and **BUILD.gn** files.
A
Annie_wang 已提交
73 74 75

     - **Makefile**:

76
       Use the **makefile** template provided by the HDF to compile the driver code.
A
Annie_wang 已提交
77 78

       
79 80
       ```c
       include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # (Mandatory) Import the HDF predefined content.
A
Annie_wang 已提交
81 82 83 84
       MODULE_NAME :=        # File to be generated.
       LOCAL_INCLUDE: =      # Directory of the driver header files.
       LOCAL_SRCS : =        # Source code files of the driver.
       LOCAL_CFLAGS : =      # Custom build options.
85
       include $(HDF_DRIVER) # Import the makefile template to complete the build.
A
Annie_wang 已提交
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:
A
Annie_wang 已提交
89 90

       
91
       ```c
A
Annie_wang 已提交
92
       LITEOS_BASELIB += -lxxx # Static library generated by the link.
93
       LIB_SUBDIRS    +=         # Directory in which makefile is located.
A
Annie_wang 已提交
94 95 96 97 98 99 100
       ```

     - **BUILD.gn**:

       Add **BUILD.gn**. The content of **BUILD.gn** is as follows:

       
101
       ```c
A
Annie_wang 已提交
102
       import("//build/lite/config/component/lite_component.gni")
103
       import("//drivers/hdf_core/adapter/khdf/liteos/hdf.gni")
A
Annie_wang 已提交
104 105 106 107 108 109 110 111 112 113
       module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
       module_name = "xxx"
       hdf_driver(module_name) {
           sources = [
               "xxx/xxx/xxx.c",           # Source code to compile.
           ]
           public_configs = [ ":public" ] # Head file configuration of the dependencies.
       }
       config("public") {                 # Define the head file configuration of the dependencies.
           include_dirs = [
114
               "xxx/xxx/xxx",             # Directory of dependency header files.
A
Annie_wang 已提交
115 116 117 118
           ]
       }
       ```

119
       Add the **BUILD.gn** directory to **/drivers/hdf_core/adapter/khdf/liteos/BUILD.gn**.
A
Annie_wang 已提交
120 121

       
122
       ```c
A
Annie_wang 已提交
123 124 125
       group("liteos") {
           public_deps = [ ":$module_name" ]
               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.
A
Annie_wang 已提交
127 128 129
               ]
       }
       ```
A
Annie_wang 已提交
130
   - Linux
A
annie_wangli 已提交
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**.
A
annie_wangli 已提交
133

A
Annie_wang 已提交
134
     
135
     ```c
A
Annie_wang 已提交
136 137
     source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
     ```
A
annie_wangli 已提交
138

139
     Add the driver directory to **drivers/hdf_core/adapter/khdf/linux/Makefile**.
A
Annie_wang 已提交
140 141

     
142
     ```c
A
Annie_wang 已提交
143 144 145 146 147 148
     obj-$(CONFIG_DRIVERS_HDF)  += xxx/
     ```

     Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.

     
149
     ```c
A
Annie_wang 已提交
150 151 152 153
     obj-y  += xxx.o
     ```

3. Configure the driver.
A
Annie_wang 已提交
154

A
Annie_wang 已提交
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).
A
annie_wangli 已提交
156 157 158

   The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.

A
Annie_wang 已提交
159
   - (Mandatory) Set driver device information.
A
annie_wangli 已提交
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:
A
Annie_wang 已提交
162 163

     
A
annie_wangli 已提交
164 165 166 167
      ```
      root {
          device_info {
              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.
A
annie_wangli 已提交
169 170
                  hostName = "";
                  priority = 100;
A
Annie_wang 已提交
171 172 173
                  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.
                  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.
                  caps = [""]];     // Linux capabilities of the user-mode process. It is left empty by default. Set this parameter based on service requirements.
A
annie_wangli 已提交
174 175 176 177 178 179 180 181 182 183 184 185 186
                  template device {
                      template deviceNode {
                          policy = 0;
                          priority = 100;
                          preload = 0;
                          permission = 0664;
                          moduleName = "";
                          serviceName = "";
                          deviceMatchAttr = "";
                      }
                  }
              }
              sample_host :: host{
A
Annie_wang 已提交
187 188
                  hostName = "host0";    // Host name. The host node is used as a container to hold a type of drivers.
                  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.
A
annie_wangli 已提交
190 191
                  device_sample :: device {        // Sample device node.
                      device0 :: deviceNode {      // DeviceNode of the sample driver.
A
Annie_wang 已提交
192
                          policy = 1;              // Policy for publishing the driver service. For details, see Driver Service Management.
A
Annie_wang 已提交
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 195 196
                          preload = 0;             // The value 0 means to load the driver by default during the startup of the system.
                          permission = 0664;       // Permission for the DeviceNode created.
                          moduleName = "sample_driver";      // Driver name. The value must be the same as that of moduleName in the HdfDriverEntry structure.
A
Annie_wang 已提交
197
                          serviceName = "sample_service";    // Name of the service published by the driver. The service name must be unique.
A
annie_wangli 已提交
198 199 200 201 202 203 204
                          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.
                      }
                  }
              }
          }
      }
      ```
A
Annie_wang 已提交
205 206 207 208 209 210 211 212 213
     
      > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/>
      >
      > - **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
      >
      > - 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.
      >
      > - If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
      >
C
chengjinsong2 已提交
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).
A
Annie_wang 已提交
215
      >
216 217 218
      > - 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"]**.
      >
      > - **preload** specifies the driver loading policy. For details, see [Driver Loading](../driver/driver-hdf-load.md).
A
annie_wangli 已提交
219 220


A
Annie_wang 已提交
221
   - (Optional) Set driver private information.
A
Annie_wang 已提交
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:
A
Annie_wang 已提交
224

A
Annie_wang 已提交
225
     
226 227
      ```
      root {
A
annie_wangli 已提交
228 229 230
          SampleDriverConfig {
              sample_version = 1;
              sample_bus = "I2C_0";
A
Annie_wang 已提交
231
              match_attr = "sample_config"; // The value must be the same as that of deviceMatchAttr in device_info.hcs.
A
annie_wangli 已提交
232 233
          }
      }
234 235 236
      ```

      Add the configuration file to the **hdf.hcs** file. <br>The following is an example:
A
Annie_wang 已提交
237

238 239 240 241 242
     
      ```
      #include "device_info/device_info.hcs"
      #include "sample/sample_config.hcs"
      ```