driver-hdf-development.md 11.6 KB
Newer Older
W
wenjun 已提交
1 2
# Driver Development<a name="EN-US_TOPIC_0000001051930361"></a>

A
annie_wangli 已提交
3
-   [Driver Model](#section157425168112)
N
NEEN 已提交
4 5
-   [How to Develop](#section1969312275533)

A
annie_wangli 已提交
6
## Driver Model<a name="section157425168112"></a>
W
wenjun 已提交
7

A
annie_wangli 已提交
8
The HDF is designed based on the component-based driver model. This model allows refined driver management and normalizes driver development and deployment. Device drivers of the same type are placed in the same host. You can develop and deploy the drivers separately. One driver can have multiple nodes.  [Figure 1](#fig3580184214210)  shows the HDF driver model.
W
wenjun 已提交
9

D
duangavin123 已提交
10 11
**Figure  1**  HDF driver model<a name="fig3580184214210"></a>  
![](figures/hdf-driver-model.png "hdf-driver-model")
W
wenjun 已提交
12 13 14

## How to Develop<a name="section1969312275533"></a>

A
annie_wangli 已提交
15
Driver development based on the HDF involves driver implementation and driver configuration. The development procedure is as follows:
W
wenjun 已提交
16

A
annie_wangli 已提交
17
1.  <a name="li35182436435"></a>Implement a driver.
W
wenjun 已提交
18 19 20 21 22 23 24

    To implement a driver, compile driver service code and register a driver entry.

    -   Driver service code

        ```
        #include "hdf_device_desc.h"  // Header file that describes the APIs provided by the HDF to the driver.
D
duangavin123 已提交
25
        #include "hdf_log.h"          // Header file that describes the log APIs provided by the HDF.
W
wenjun 已提交
26
        
D
duangavin123 已提交
27
        #define HDF_LOG_TAG "sample_driver"   // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
W
wenjun 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
        
        // The driver service interface must be bound to the HDF for you to use the service capability.
        int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
        {
            HDF_LOGD("Sample driver bind success");
            return 0;
        }
        
        // Initialize the driver service.
        int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
        {
            HDF_LOGD("Sample driver Init success");
            return 0;
        }
        
        // Release the driver resources.
        void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
        {
            HDF_LOGD("Sample driver release success");
            return;
        }
        ```

    -   Registering the driver entry with the HDF

        ```
        // Define the object of the driver entry. The object 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,
        };
        
        // Call HDF_INIT to register the driver entry with the HDF framework. When loading the driver, call the Bind function and then the Init function. If the Init function fails to be called, the HDF will call Release to release the driver resource and exit.
        HDF_INIT(g_sampleDriverEntry);
        ```

A
annie_wangli 已提交
67
2. Build the driver.
W
wenjun 已提交
68

A
annie_wangli 已提交
69
   - LiteOS
W
wenjun 已提交
70

A
annie_wangli 已提交
71
     Modify **makefile** and **BUILD.gn**:
W
wenjun 已提交
72

A
annie_wangli 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
     * makefile:

       Use the **makefile** template provided by the HDF to compile the driver code.

       ```
       include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory.
       MODULE_NAME :=    # File to be generated.
       LOCAL_INCLUDE: =  # Header file directory of the driver.
       LOCAL_SRCS : =     # Source code file of the driver.
       LOCAL_CFLAGS : =  # Custom compilation options.
       include $(HDF_DRIVER) # Import the makefile template to complete the compilation.
       ```

       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. The following is an example:

       ```
       LITEOS_BASELIB += -lxxx # Static library generated by the link.
       LIB_SUBDIRS    +=         # Directory in which the driver code makefile is located.
       ```

     * BUILD.gn:

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

       ```
       import("//build/lite/config/component/lite_component.gni")
       import("//drivers/adapter/khdf/liteos/hdf.gni")
       module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
       module_name = "xxx"
       hdf_driver(module_name) {
           sources = [
               "xxx/xxx/xxx.c", # Source code file of the driver 
           ]
           public_configs = [ ":public" ] # Configuration applied to dependencies
       }
       config("public") {# Configuration of the dependencies
           include_dirs = [
		   "xxx/xxx/xxx", # Directory of the dependency header file.
           ]
       }
       ```

       Add the directory where the **BUILD.gn** file of the driver is located to **/drivers/adapter/khdf/liteos/BUILD.gn**.

       ```
       group("liteos") {
              public_deps = [ ":$module_name" ]
                  deps = [
                     "xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos.
                 ]
       }
       ```

   - Linux

     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**.

     ```
     source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
     ```

     Add the driver directory to **drivers/adapter/khdf/linux/Makefile**.

     ```
     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.

     ```
     obj-y  += xxx.o
     ```
W
wenjun 已提交
145 146 147

3.  Configure the driver.

A
annie_wangli 已提交
148
    HDF Configuration Source (HCS) is the source code that describes the configuration of the HDF. For details about the HCS, see [Driver Configuration Management](driver-hdf-manage.md).
W
wenjun 已提交
149 150 151

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

A
annie_wangli 已提交
152
    -   (Mandatory) Driver device description
W
wenjun 已提交
153

A
annie_wangli 已提交
154
        The information required for the HDF to load drivers comes from the driver device description defined by the HDF. Therefore, the device description must be added to the configuration file **device_info.hcs** defined by the HDF for drivers developed based on the HDF.The following is an example:
W
wenjun 已提交
155 156 157 158 159 160 161

        ```
        root {
            device_info {
                match_attr = "hdf_manager";
                template host {       // Host template. If the node (for example, sample_host) that inherits the template uses default values in the template, the values of the node fields can be omitted.
                    hostName = "";
W
wenjun 已提交
162 163 164 165 166 167 168 169 170 171 172
                    priority = 100;
                    template device {
                        template deviceNode {
                            policy = 0;
                            priority = 100;
                            preload = 0;
                            permission = 0664;
                            moduleName = "";
                            serviceName = "";
                            deviceMatchAttr = "";
                        }
W
wenjun 已提交
173 174 175 176 177
                    }
                }
                sample_host :: host{
                    hostName = "host0";    // Host name. The host node is used to store a certain type of drivers.
                    priority = 100;        // Host startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence is random.
W
wenjun 已提交
178 179
                    device_sample :: device {        // Device node of sample
                        device0 :: deviceNode {      // DeviceNode of the sample driver
N
NEEN 已提交
180 181
                            policy = 1;              // Driver service release policy. For details, see section Driver Service Management.
                            priority = 100;          // Driver startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the device loading sequence is random.
D
duangavin123 已提交
182
                            preload = 0;             // On-demand loading of the driver. For details, see "NOTE" at the end of this section.
N
NEEN 已提交
183 184 185
                            permission = 0664;       // Permission for the driver to create device nodes.
                            moduleName = "sample_driver";   // Driver name. The value of this field must be the same as the value of moduleName in the driver entry structure.
                            serviceName = "sample_service";    // Name of the service released by the driver. The name must be unique.
W
wenjun 已提交
186 187
                            deviceMatchAttr = "sample_config"; // Keyword 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.
                        }
W
wenjun 已提交
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
                    }
                }
            }
        }
        ```

    -   \(Optional\) Private configuration information of the driver

        If the driver has private configurations, you can add a driver configuration file to fill in the default configuration information of the driver. When loading the driver, the HDF obtains the information and saves it in the  **property**  of  **HdfDeviceObject**, and transfers it to the driver using  **Bind**  and  **Init**  \(see  [1](#li35182436435)\). The following is an example of the driver configuration information:

        ```
        root {
            SampleDriverConfig {
                sample_version = 1;
                sample_bus = "I2C_0";
                match_attr = "sample_config"; // The value of this field must be the same as that of deviceMatchAttr in device_info.hcs.
            }
        }
        ```

        After the configuration information is defined, you need to add the configuration file to the board-level configuration entry file  **hdf.hcs**. \(You can use the DevEco to perform on-click configuration. For details, see the description about the driver development suite.\) The following is an example:

        ```
        #include "device_info/device_info.hcs"
        #include "sample/sample_config.hcs"
        ```



D
duangavin123 已提交
217
>![](../public_sys-resources/icon-note.gif) **NOTE:** 
W
wenjun 已提交
218 219 220 221 222
>On-demand loading and sequential loading are supported. The detailed usage is as follows:
>-   On-demand loading
>    ```
>    typedef enum {
>        DEVICE_PRELOAD_ENABLE = 0,
M
mamingshuai 已提交
223
>        DEVICE_PRELOAD_ENABLE_STEP2,
W
wenjun 已提交
224 225 226 227
>        DEVICE_PRELOAD_DISABLE,
>        DEVICE_PRELOAD_INVALID
>    } DevicePreload;
>    ```
A
annie_wangli 已提交
228
>    If the **preload** field in the configuration file is set to **0** (DEVICE\_PRELOAD\_ENABLE), the driver is loaded by default during the system boot process. If **preload** is set to **1** (DEVICE\_PRELOAD\_ENABLE\_STEP2), the driver is loaded after a quick start is complete if the system supports quick start. If the system does not support quick start, the value **1** has the same meaning as DEVICE\_PRELOAD\_ENABLE. 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 (for details, see [Driver Message Mechanism Management](driver-hdf-news.md)), the HDF attempts to dynamically load the driver if the driver service does not exist.
W
wenjun 已提交
229 230
>-   Sequential loading \(drivers must be loaded by default\)
>    In the configuration file, the  **priority**  field \(the value is an integer ranging from 0 to 200\) indicates the priority of the host and 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.