diff --git a/en/device-dev/driver/driver-hdf-development.md b/en/device-dev/driver/driver-hdf-development.md index 055ac4778eb0ab946793ae30be6f2f4f2770f12a..a690d42bf3ebd1c47689c6f8eb72c52379701e4e 100644 --- a/en/device-dev/driver/driver-hdf-development.md +++ b/en/device-dev/driver/driver-hdf-development.md @@ -3,11 +3,11 @@ ## Driver Model -The 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. +The 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. The figure below shows the HDF driver model. - **Figure 1** HDF driver model +**Figure 1** HDF driver model ![](figures/hdf-driver-model.png) @@ -16,87 +16,90 @@ The figure below shows the HDF driver model. The HDF-based driver development involves driver implementation and configuration. The procedure is as follows: -1. Implement a driver.
+1. Implement a driver. + Write the driver code and register the driver entry with the HDF. - + - Writing the driver service code The following is an example: - - ``` - #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. - - #define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used. - - // Bind the service interface provided by the driver to the HDF. - 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; - } - ``` - + + ``` + #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. + + #define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used. + + // Bind the service interface provided by the driver to the HDF. + 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 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, + }; + + // 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. + HDF_INIT(g_sampleDriverEntry); + ``` +2. Build the driver. - ``` - // 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, - }; + - LiteOS - // 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. - HDF_INIT(g_sampleDriverEntry); - ``` + Modify **makefile** and **BUILD.gn**. -2. Build the driver.
- - LiteOS
- Modify the **Makefile** and **BUILD.gn** files. - - **Makefile**:
- Use the **makefile** template provided by the HDF to compile the driver code. - - + + 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: = # Directory of the driver header files. LOCAL_SRCS : = # Source code file of the driver. LOCAL_CFLAGS : = # Custom compilation options. - include $(HDF_DRIVER) # Import the makefile template to complete the compilation. + include $(HDF_DRIVER) # Import the Makefile template to complete the build. ``` - - 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. - - + + 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 Makefile is located. ``` - - - **BUILD.gn**:
- Add **BUILD.gn**. The content of **BUILD.gn** is as follows: - - + + - **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") @@ -114,10 +117,10 @@ The HDF-based driver development involves driver implementation and configuratio ] } ``` - + Add the **BUILD.gn** directory to **/drivers/adapter/khdf/liteos/BUILD.gn**. - - + + ``` group("liteos") { public_deps = [ ":$module_name" ] @@ -126,37 +129,41 @@ The HDF-based driver development involves driver implementation and configuratio ] } ``` - - 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**. + + - 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 file. - + ``` obj-y += xxx.o ``` - + 3. Configure the driver.
+ 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). The driver configuration consists of the driver device description defined by the HDF and the private driver configuration. - (Mandatory) Setting the driver device description
- 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: - + 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: + + ``` root { device_info { @@ -185,12 +192,12 @@ The HDF-based driver development involves driver implementation and configuratio caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // Linux capabilities of the user-mode process. device_sample :: device { // Sample device node. device0 :: deviceNode { // DeviceNode of the sample driver. - policy = 1; // Policy for providing the driver service. For details, see Driver Service Management. + policy = 1; // Policy for publishing the driver service. For details, see Driver Service Management. 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. preload = 0; // The loading mode of the driver is on-demand loading. For details, see "NOTE" at the end of this document. permission = 0664; // Permission for the driver to create a device node. - moduleName = "sample_driver"; // Driver name. The value must be the same as that of moduleName in the HdfDriverEntry structure. - serviceName = "sample_service"; // Name of the service provided by the driver. The service name must be unique. + moduleName = "sample_driver"; // Driver name. The value of this field must be the same as that of moduleName in the HdfDriverEntry structure. + serviceName = "sample_service"; // Name of the service published by the driver. The service name must be unique. 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. } } @@ -201,19 +208,21 @@ The HDF-based driver development involves driver implementation and configuratio ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**
- **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. + - 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). - - If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**. - + - If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**. - (Optional) Setting driver private information
+ 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). - + The following is an example of the driver private configuration: - ``` root { SampleDriverConfig { @@ -225,21 +234,20 @@ The HDF-based driver development involves driver implementation and configuratio ``` 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.) - + The following is an example: - ``` #include "device_info/device_info.hcs" #include "sample/sample_config.hcs" ``` -> ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**
+> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Drivers can be loaded on demand or in sequence. -> +> > - On-demand loading -> +> > ``` > typedef enum { > DEVICE_PRELOAD_ENABLE = 0, @@ -248,12 +256,12 @@ The HDF-based driver development involves driver implementation and configuratio > DEVICE_PRELOAD_INVALID > } DevicePreload; > ``` -> +> > If **preload** 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 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, 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). -> +> > - Sequential loading (**preload** set to **0 (DEVICE_PRELOAD_ENABLE)**)
-> 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. +> In the configuration file, the **priority** field (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. diff --git a/en/device-dev/driver/driver-hdf-manage.md b/en/device-dev/driver/driver-hdf-manage.md index abef772fb0614ea627a96fc9bc91a9051876597f..938fe06a0c51cdb09c2e1e430d02b1844b1cde19 100644 --- a/en/device-dev/driver/driver-hdf-manage.md +++ b/en/device-dev/driver/driver-hdf-manage.md @@ -48,12 +48,12 @@ The HCS has two structures: attribute and node. An attribute is the minimum, independent configuration unit. The syntax is as follows: - + ``` attribute_name = value; ``` -- **attribute_name** is a case-sensitive string of letters, digits, and underscores (_) and must start with a letter or underscore (_). +- **attribute_name** is a case-sensitive string of letters, digits, and underscores (\_) and must start with a letter or underscore (_). - The **value** can be in any of the following formats: @@ -67,7 +67,7 @@ An attribute is the minimum, independent configuration unit. The syntax is as fo A node is a set of attributes. The syntax is as follows: - + ``` node_name { module = "sample"; @@ -75,7 +75,7 @@ A node is a set of attributes. The syntax is as follows: } ``` -- **node_name** is a case-sensitive string of letters, digits, and underscores (_) and must start with a letter or underscore (_). +- **node_name** is a case-sensitive string of letters, digits, and underscores (\_) and must start with a letter or underscore (_). - No semicolon (;) is required after the curly brace ({) or (}). @@ -109,7 +109,7 @@ A string is enclosed in double quotation marks (""). An array can hold either integers or strings, but not a mixture 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: - + ``` attr_foo = [0x01, 0x02, 0x03, 0x04]; attr_bar = ["hello", "world"]; @@ -126,7 +126,7 @@ Boolean data type is a form of data with only two possible values: **true** and The keyword **include** is used to import other HCS files. The syntax is as follows: - + ``` #include "foo.hcs" #include "../bar.hcs" @@ -143,14 +143,14 @@ The following two comment formats are supported: - Single-line comment - + ``` // comment ``` - Multi-line comment - + ``` /* comment @@ -165,15 +165,14 @@ The following two comment formats are supported: You can reference the content of a node to modify the content of another node. The syntax is as follows: - + ``` node :& source_node ``` In this statement, the content of **node** is referenced to modify the content of **source_node**. - + Example: - ``` root { module = "sample"; @@ -197,7 +196,7 @@ root { The configuration tree generated is as follows: - + ``` root { module = "sample"; @@ -223,7 +222,7 @@ In this example, the value of **bar.attr** is changed to **foo** by referencing You can replicate a node to define a node with similar content. The syntax is as follows: - + ``` node : source_node ``` @@ -231,8 +230,7 @@ You can replicate a node to define a node with similar content. The syntax is as This statement replicates the attributes of the **source_node** node to define **node**. Example: - - + ``` root { module = "sample"; @@ -247,7 +245,7 @@ root { The configuration tree generated is as follows: - + ``` root { module = "sample"; @@ -263,7 +261,7 @@ root { In 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. -You do not need to specify the path of the **foo** node if the **foo** node and the **bar** node are of the same level. Otherwise, specify the absolute path of **foo**. For details, see [Reference Modification](referencemodification). +You do not need to specify the path of the **foo** node if the **foo** node and the **bar** node are of the same level. Otherwise, specify the absolute path of **foo**. For details, see [Reference Modification](#reference-modification). ### Delete @@ -271,8 +269,7 @@ You do not need to specify the path of the **foo** node if the **foo** node and You 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. Example: - - + ``` // sample2.hcs root { @@ -294,7 +291,7 @@ root { The configuration tree generated is as follows: - + ``` root { attr_1 = 0x1; @@ -309,7 +306,7 @@ root { You 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: - + ``` attribute = &node; ``` @@ -317,8 +314,7 @@ You can associate an attribute and a node so that the node can be quickly locate In 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**. Example: - - + ``` node1 { attributes; @@ -328,9 +324,9 @@ node2 { } ``` -Or - +or + ``` node2 { node1 { @@ -348,8 +344,7 @@ The template is used to generate nodes with consistent syntax, thereby facilitat 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. Example: - - + ``` root { module = "sample"; @@ -369,7 +364,7 @@ root { The configuration tree generated is as follows: - + ``` root { module = "sample"; @@ -396,7 +391,7 @@ The HC-GEN tool checks the HCS configuration syntax and converts HCS source file HC-GEN options: - + ``` Usage: hc-gen [Options] [File] options: @@ -415,28 +410,28 @@ options: Generate a .c or .h configuration file. - + ``` hc-gen -o [OutputCFileName] -t [SourceHcsFileName] ``` Generate an HCB file. - + ``` hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName] ``` Generate a macro definition file. - + ``` hc-gen -o [OutputMacroFileName] -m [SourceHcsFileName] ``` Decompile an HCB file to an HCS file. - + ``` hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName] ``` diff --git a/en/device-dev/driver/driver-hdf-sample.md b/en/device-dev/driver/driver-hdf-sample.md index 93d1e3a03ba915957b9de7e0f34e83cf87e52d0b..29288f97467bd55616335e1f5505335526d85e89 100644 --- a/en/device-dev/driver/driver-hdf-sample.md +++ b/en/device-dev/driver/driver-hdf-sample.md @@ -232,7 +232,7 @@ int main() } ``` -> ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**
+> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> 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: > > deps = [ diff --git a/en/device-dev/driver/figures/HCB-using-process.png b/en/device-dev/driver/figures/HCB-using-process.png index 3803784ebc2200f61b79420e52b010cad1a55eab..e55e4cb9154a8b06ac3cae38a4a5835ac6082431 100644 Binary files a/en/device-dev/driver/figures/HCB-using-process.png and b/en/device-dev/driver/figures/HCB-using-process.png differ diff --git a/en/device-dev/driver/figures/hdf-driver-model.png b/en/device-dev/driver/figures/hdf-driver-model.png index f2a5855dfeea0eaa8e4db38323b25858ef6a1e09..e524ecca84ab2afd674c73abd76ae2ebcc50cb9a 100644 Binary files a/en/device-dev/driver/figures/hdf-driver-model.png and b/en/device-dev/driver/figures/hdf-driver-model.png differ