提交 4e8a86b5 编写于 作者: D duxbbo

Merge branch 'master' of gitee.com:openharmony/docs into FixDocsBug

Change-Id: I173015f738ad4991cf11ced392a51d88f9efd22a

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
......@@ -358,9 +358,9 @@ OpenHarmony archived projects: [https://gitee.com/openharmony-retired](https://
## OpenHarmony Documentation<a name="section21031470109"></a>
[Chinese version](https://gitee.com/openharmony/docs/blob/master/Readme-zh-cn.md)
[Chinese version](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme.md)
[English version](https://gitee.com/openharmony/docs/blob/master/Readme-en.md)
[English version](https://gitee.com/openharmony/docs/blob/master/en/readme.md)
## Source Code Downloading<a name="section39011923144212"></a>
......
# Bundle Development
- [Development Specifications](development-specifications.md)
- [Overview](overview.md)
- [Bundle Composition](bundle-composition.md)
- [Bundle Management](bundle-management.md)
- [Bundle Version](bundle-version.md)
- [Distribution](distribution.md)
- [Environment Variables](environment-variables.md)
- [Development Guidelines](development-guidelines.md)
- [Overview](overview-0.md)
- [Preparations](preparations.md)
- [Bundle Development](bundle-development.md)
- [HPM User Guide](hpm-user-guide.md)
- [Introduction](introduction.md)
- [Preparations](preparations-1.md)
- [Development Example](development-example.md)
# Bundle Development
- [Development Specifications](bundles-standard-rules.md)
- [Development Guidelines](bundles-guide.md)
- [Bundle Development](bundles-guide-overview.md)
- [Preparations](bundles-guide-prepare.md)
- [Bundle Development](bundles-guide-develop.md)
- [HPM User Guide](bundles-demo.md)
- [Introduction](bundles-demo-hpmdescription.md)
- [Preparations](bundles-demo-environment.md)
- [Development Example](bundles-demo-devsample.md)
\ No newline at end of file
# Bundle Composition<a name="EN-US_TOPIC_0000001051930853"></a>
- [Code files](#section101483489110)
- [README File](#section10519101221211)
- [Metadata Description File](#section45511827111211)
A bundle contains the following contents:
- **src** directory for storing code files or code library
- **ohos\_bundles** folder for storing dependent bundles \(It is automatically generated during bundle installation, without the need to submit to the code library.\)
- **README.md** file for describing the bundle
- **bundle.json** file for declaring metadata of the bundle
- **LICENSE** file for open-source code
```
my-bundle
|_ohos_bundles
|_src
|_bundle.json
|_README.md
|_LICENSE
```
## Code files<a name="section101483489110"></a>
Bundle code files are the same as those in a common code directory. The only difference lies in the open APIs \(declared in header files\) of a bundle, which are likely to be referenced by other bundles and need to be declared in the **dirs** of **bundle.json**.
## README File<a name="section10519101221211"></a>
**README.md** is a bundle self-description file using the markdown syntax. For details, see [Syntax Reference](https://www.markdownguide.org/getting-started/).
To help you easily find and use the desired bundle on the HarmonyOS Package Manager \(HPM\) platform, a **README** file is provided in the root directory of each bundle.
The **README** file may include instructions on how to install, configure, and use the instance code in the bundle, as well as any other information helpful to you.
The **README** file is available in the bundle details page of the HPM platform.
## Metadata Description File<a name="section45511827111211"></a>
A **bundle.json** file describes the metadata of a bundle. Each bundle has its own **bundle.json** file.
```
{
"name": "@myorg/demo-bundle",
"version": "1.0.0",
"license": "MIT",
"description": "bundle description",
"keywords": ["hos"],
"tags": ["applications", "drivers"],
"author": {"name":"","email":"","url":""},
"contributors":[{"name":"","email":"","url":""},{"name":"","email":"","url":""}],
"homepage": "http://www.foo.bar.com",
"repository": "https://git@gitee.com:foo/bar.git",
"publishAs": "source",
"dirs": {
"src": ["src/**/*.c"],
"headers": ["headers/**/*.h"],
"bin": ["bin/**/*.o"]
},
"scripts": {
"build": "make"
},
"envs": {},
"ohos": {
"os": "2.0.0",
"board": "hi3516",
"kernel": "liteos-a"
},
"rom": "10240",
"ram": "1024",
"dependencies": {
"@myorg/net":"1.0.0"
}
}
```
Each **bundle.json** file has the following fields:
- **name**: a bundle name, which starts with @ and is separated by /, for example, **@myorg/mybundle**
- **version**: a bundle version number, for example, 1.0.0. The version number must comply with the Semantic Versioning Specification \(SemVer\) standards.
- **description**: a brief description of a bundle
- **dependencies**: bundles that a bundle depends on
- **envs**: parameters required for bundle compilation, including global parameters and dependency parameters.
- **scripts**: commands executable to a bundle, such as those for compiling, building, testing, and burning
- **publishAs**: bundle publishing type, which can be **source**, **binary**, **distribution**, or **code-segment**
- **dirs**: directory structure \(such as the header file\) generated for publishing
- **ram&rom**: statistical information about the estimated read-only memory \(ROM\) and random access memory \(RAM\) usage
- **ohos**: mappings among OpenHarmony versions, development boards, and kernels, separated by commas \(,\).
- Extended information: author, home page, code repository, license, tags, and keywords
- **base** \(only for a distribution\): a base distribution which others inherit from.
# Bundle Development<a name="EN-US_TOPIC_0000001051690861"></a>
- [Developing a OpenHarmony Bundle](#section1976410130540)
- [Creating a Bundle](#section717481119145)
- [Modifying a Bundle](#section102861955201410)
- [Using HPM-provided Template to Create a Bundle](#section15882846181510)
- [Building a Bundle](#section136732148541)
- [Defining the Building Script](#section10274147111610)
- [Executing the Building Script](#section879301916172)
- [Defining a Distribution](#section413216495619)
- [Defining Scripts](#section11503171219190)
- [Distributing](#section4694125521912)
- [Burning](#section1746331545413)
- [Debugging](#section6742131615549)
## Developing a OpenHarmony Bundle<a name="section1976410130540"></a>
You have an option to use any of the following methods to develop an OpenHarmony bundle:
- Develop a brand new bundle from scratch.
- Rewrite code of an existing non-bundle to develop a bundle.
- Use HPM-provided bundle templates to quickly develop a bundle.
## Creating a Bundle<a name="section717481119145"></a>
Generally, you can find commonly used bundles on the [HPM](https://hpm.harmonyos.com/#/en/home) website. If they cannot meet your requirements, you can develop your own bundles.
You can publish bundles in the HPM repository if you like, so that your peers have an option to use them. Assume that you want to create a bundle named **my-bundle** in the **D:/source** directory:
Run the **hpm init** command to create the scaffold code for this bundle. For example, you can go to the **D:/source** directory and run the following command:
```
hpm init -t default -d demo my-bundle
```
The following files are generated in the **source** directory:
```
mybundle
├── bundle.json # Metadata description file of the bundle
├── example # Example of testing bundle functions
│ └── main.c
├── include # Internal header files of the bundle
│ └── mybundle.h
├── README.md # Brief description of the bundle
└── src # Source code of the bundle
└─ mybundle.c
```
Then, complete your coding based on service requirements. Finally, use **git** to commit your code \(including the **bundle.json** file\) to the code hosting repository, such as gitee.
## Modifying a Bundle<a name="section102861955201410"></a>
If you have code unqualified for the OpenHarmony bundle structure, modify your code to match an HPM bundle. In the code directory \(for example, **mybundle2**\) storing your code, run the following command with the bundle name and version specified:
```
hpm init
```
1. Enter a bundle name \(**mybundle2** as an example\) and press **Enter**.
2. Enter the bundle version \(**1.0.0** as an example\) and press **Enter**. A **bundle.json** file is generated in the current bundle directory.
3. Add other descriptions in **bundle.json**, which is publishable.
```
$ hpm init
Your bundle will be created in dirname E:\demo\mybundle2
? bundle name mybundel2
? version 1.0.0
Init finished!
```
1. Modify other information \(such as the author, code repository, code directory, command script, and dependent bundles\) in **bundle.json**.
```
{
"name": "mybundle2",
"version": "1.0.0",
"publishAs": "source",
"dirs":{
".":[
"README.md"
],
"src":[
"test.c"
],
"header":[
"header/test.h"
],
"src/common":[
"src/common/foobar.txt"
]
},
"scripts": {
"build": "make -${args}"
},
"dependencies": {
"@ohos/cjson": "^1.0.0",
"@ohos/": "^1.2.0"
}
}
```
## Using HPM-provided Template to Create a Bundle<a name="section15882846181510"></a>
The HPM provides **default** and **simple** templates as well as other templates that are stored on the server.
You can run the **hpm search -t template** command to search for a template stored on the server.
![](figures/en-us_image_0000001051452177.png)
Then, select your desired template based on the information below **description**, use the selected template to quickly create the bundle scaffold, and run the following command with the **-t** and **-d** parameters specified:
```
hpm init -t {templatename} -d dir name
```
- **\{templatename\}** indicates the template name.
- **dir** indicates the path for storing the bundle to be created.
- **name** indicates the name of the bundle to be created.
## Building a Bundle<a name="section136732148541"></a>
After completing code development, you need to build the bundle. The HPM supports command integration so that you can select any build tool \(such as **make**, **gcc**, and **gn**\) suitable for your project. You only need to define the **build** command in the **scripts** in the **bundle.json** file of your project, and then you run the hpm command **build** to perform building.
## Defining the Building Script<a name="section10274147111610"></a>
This section uses how to build an executable file **helloworld** in the **app** directory as an example.
```
app
├── BUILD.gn
├── include
│ └── helloworld.h
└── src
└── helloworld.c
```
Create a **BUILD.gn** file in the same directory as **helloworld.c**.
```
touch BUILD.gn
vim BUILD.gn
```
The following is an example of **BUILD.gn** for your reference:
```
executable("hello_world") {
sources = [
"src/helloworld.c"
]
include_dirs = [
"include"
]
}
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>- **executable** is a built-in template of **gn**. You can run the **gn help executable** command to view how to use this template.
>- **sources** represents the source code path, and **include\_dirs** represents the header file path.
## Executing the Building Script<a name="section879301916172"></a>
Run the following command:
```
hpm build
```
After all building operations are complete, the message "build succeed" is displayed. You need to check the building result.
![](figures/en-us_image_0000001051770876.png)
## Defining a Distribution<a name="section413216495619"></a>
A distribution refers to an image file of an executable OpenHarmony solution composed of a group of bundles. It contains many dependent bundles and provides scripts to illustrate how to compile and link these bundles.
## Defining Scripts<a name="section11503171219190"></a>
Define scripts in **bundle.json** as follows:
```
{
"name": "my_dist",
"version": "1.0.0",
"publishAs": "distribution",
"scripts": {
"dist": "make -${args}"
},
"base": {
"name": "dist-bundle",
"version": "1.0.0"
},
"envs": {
"args": "x86"
},
"dependencies": {
}
}
```
## Distributing<a name="section4694125521912"></a>
Run the following command in the current distribution directory:
```
hpm dist
```
The **hpm-cli** tool automatically performs compiling and packing, and generates an image file of the **dist** script defined based on **scripts**. The following is an example:
```
out
|-xxdist.img
|-xx.file
```
## Burning<a name="section1746331545413"></a>
The building result of the distribution can be burnt into devices, for example, by using the **hiburn** tool. You need to configure burning parameters in the **bundle.json** file of the distribution.
```
"scripts": {
"flash": "{$DEP_HIBURN}/hiburn"
},
```
You should set burning parameters by referring to the specific guide on the burning tool you use.
```
hpm run flash
```
## Debugging<a name="section6742131615549"></a>
Start debugging after you have burnt the image file of the distribution into devices. The debugging process varies according to specific development boards and IDE debugging tools.
# Bundle Management<a name="EN-US_TOPIC_0000001052170830"></a>
- [Dependency](#section12657593129)
- [HPM Command Reference](#section1258849181312)
## Dependency<a name="section12657593129"></a>
A basic **bundle.json** file needs to be enriched by bundle dependencies to implement more complex features. Bundle names and version numbers should be defined in the **dependencies** field of **bundle.json**.
```
{
"name": "my-bundle",
"version": "1.0.0",
"dependencies": {
"net": "1.0.0"
}
}
```
In this example, **my-bundle** depends on **net 1.0.0**. After you globally install the hpm-cli tool, run the following command to obtain bundle dependencies from the remote repository:
```
hpm install
```
Bundle dependencies are then stored in the **ohos\_bundles** folder in the root directory of the current bundle. A tree structure illustrating the bundle and its dependencies will be generated. You need to run the following command in the root directory of the bundle:
```
username@server MINGW64 /f/showcase/demo/demo
$ hpm list
+--demo@1.0.0
| +--@huawei/media@1.0.2
| +--@demo/sport_hi3518ev300_liteos_a@1.0.0
| | +--@demo/app@4.0.1
| | | +--@demo/build@4.0.1
| | | +--@demo/arm_harmonyeabi_gcc@4.0.0
| | +--@demo/liteos_a@4.0.0
| | | +--@demo/third_party_fatfs@4.0.0
| | | +--@demo/arm_harmonyeabi_gcc@4.0.0
| | +--@demo/init@4.0.0
| | +--@demo/dist_tools@4.0.0
```
Alternatively, you can view the dependencies of the current bundle in a graph by running the following command:
```
hpm dependencies
```
A **deps\_visual** folder is generated in the current directory. The folder contains the **deps.html** and **deps-data.js** files. After you open the **deps.html** file via a browser, you can view bundle dependencies illustrated by a graph, as shown in the following figure.
Each dependency type is indicated by a different color at the corresponding node. You can move the mouse pointer to a node to view the implied information.
**Figure 1** Bundle dependencies<a name="fig4306113315312"></a>
![](figures/bundle-dependencies.png "bundle-dependencies")
## HPM Command Reference<a name="section1258849181312"></a>
You can use the hpm-cli tool to manage the lifecycle of a bundle. The following table describes available HPM commands. \(You can run the **hpm -h** command to get the command details\).
**Table 1** HPM commands
<a name="table10510164515371"></a>
<table><thead align="left"><tr id="row125101745103718"><th class="cellrowborder" valign="top" width="20.95209520952095%" id="mcps1.2.4.1.1"><p id="p1451014454371"><a name="p1451014454371"></a><a name="p1451014454371"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="30.623062306230626%" id="mcps1.2.4.1.2"><p id="p17510144553716"><a name="p17510144553716"></a><a name="p17510144553716"></a>Command</p>
</th>
<th class="cellrowborder" valign="top" width="48.42484248424842%" id="mcps1.2.4.1.3"><p id="p65102452371"><a name="p65102452371"></a><a name="p65102452371"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row25106453375"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p151044514378"><a name="p151044514378"></a><a name="p151044514378"></a>Querying version information</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p1653795113472"><a name="p1653795113472"></a><a name="p1653795113472"></a>hpm -V or hpm --version</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p399295684713"><a name="p399295684713"></a><a name="p399295684713"></a>Queries the <strong id="b107479812617"><a name="b107479812617"></a><a name="b107479812617"></a>hpm-cli</strong> version number.</p>
</td>
</tr>
<tr id="row651017455374"><td class="cellrowborder" rowspan="2" align="left" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p551054516372"><a name="p551054516372"></a><a name="p551054516372"></a>Querying help information</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p18648167124812"><a name="p18648167124812"></a><a name="p18648167124812"></a>hpm -h or hpm --version</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p1464811794817"><a name="p1464811794817"></a><a name="p1464811794817"></a>Queries the command list and help information.</p>
</td>
</tr>
<tr id="row1751016452379"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p16778111111487"><a name="p16778111111487"></a><a name="p16778111111487"></a>hpm -h</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1877811154818"><a name="p1877811154818"></a><a name="p1877811154818"></a>Queries command reference.</p>
</td>
</tr>
<tr id="row2511945123715"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p3955174864810"><a name="p3955174864810"></a><a name="p3955174864810"></a>Creating a project</p>
<p id="p14511184518374"><a name="p14511184518374"></a><a name="p14511184518374"></a></p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p2046811558481"><a name="p2046811558481"></a><a name="p2046811558481"></a>hpm init bundle</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p1646818557481"><a name="p1646818557481"></a><a name="p1646818557481"></a>Creates a bundle project.</p>
</td>
</tr>
<tr id="row351184593713"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p18991313496"><a name="p18991313496"></a><a name="p18991313496"></a>hpm init -t template</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p109912104911"><a name="p109912104911"></a><a name="p109912104911"></a>Creates a scaffolding project based on the template.</p>
</td>
</tr>
<tr id="row1751164511374"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p1351111454374"><a name="p1351111454374"></a><a name="p1351111454374"></a>Installing bundles</p>
<p id="p251144513715"><a name="p251144513715"></a><a name="p251144513715"></a></p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p8896182914913"><a name="p8896182914913"></a><a name="p8896182914913"></a>hpm install or hpm i</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p1289692919493"><a name="p1289692919493"></a><a name="p1289692919493"></a>Installs dependent bundles in the <strong id="b161239403810"><a name="b161239403810"></a><a name="b161239403810"></a>bundle.json</strong> file.</p>
</td>
</tr>
<tr id="row15511194563712"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p17917436134911"><a name="p17917436134911"></a><a name="p17917436134911"></a>hpm install bundle@version</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1891723611494"><a name="p1891723611494"></a><a name="p1891723611494"></a>Installs bundles of a specified version.</p>
</td>
</tr>
<tr id="row21051110155011"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p1630384435010"><a name="p1630384435010"></a><a name="p1630384435010"></a>Uninstalling bundles</p>
<p id="p83417161509"><a name="p83417161509"></a><a name="p83417161509"></a></p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p288195017502"><a name="p288195017502"></a><a name="p288195017502"></a>hpm uninstall bundle</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p2088450165014"><a name="p2088450165014"></a><a name="p2088450165014"></a>Removes dependent bundles.</p>
</td>
</tr>
<tr id="row73341617507"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p934161613508"><a name="p934161613508"></a><a name="p934161613508"></a>hpm remove or hpm rm bundlename</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p234111685016"><a name="p234111685016"></a><a name="p234111685016"></a>Removes dependent bundles.</p>
</td>
</tr>
<tr id="row166449214501"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p8645421125016"><a name="p8645421125016"></a><a name="p8645421125016"></a>Viewing information</p>
<p id="p12645202115014"><a name="p12645202115014"></a><a name="p12645202115014"></a></p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p679412535211"><a name="p679412535211"></a><a name="p679412535211"></a>hpm list or hpm ls</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p07941451526"><a name="p07941451526"></a><a name="p07941451526"></a>Displays the bundle tree of available bundles and distributions.</p>
</td>
</tr>
<tr id="row1764552105017"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p035818131525"><a name="p035818131525"></a><a name="p035818131525"></a>hpm dependencies</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19358413135217"><a name="p19358413135217"></a><a name="p19358413135217"></a>Generates the dependency diagram (in HTML format) of available bundles and distributions.</p>
</td>
</tr>
<tr id="row1553428145020"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p353202845014"><a name="p353202845014"></a><a name="p353202845014"></a>Searching for bundles</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p1423903005211"><a name="p1423903005211"></a><a name="p1423903005211"></a>hpm search name</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p17239163018524"><a name="p17239163018524"></a><a name="p17239163018524"></a>Searches for bundles. <strong id="b19633144117155"><a name="b19633144117155"></a><a name="b19633144117155"></a>--json</strong> is used to specify the search result in JSON format, and <strong id="b082012211161"><a name="b082012211161"></a><a name="b082012211161"></a>-type</strong> is used to set the target type, which can be <strong id="b145758515160"><a name="b145758515160"></a><a name="b145758515160"></a>bundle</strong>, <strong id="b1555171214178"><a name="b1555171214178"></a><a name="b1555171214178"></a>distribution</strong>, or <strong id="b0446141811713"><a name="b0446141811713"></a><a name="b0446141811713"></a>code-segment</strong>.</p>
</td>
</tr>
<tr id="row135482855018"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p38201311174016"><a name="p38201311174016"></a><a name="p38201311174016"></a>Setting HPM configuration items</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p279915013522"><a name="p279915013522"></a><a name="p279915013522"></a>hpm config set key value</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p157991450205211"><a name="p157991450205211"></a><a name="p157991450205211"></a>Sets configuration items, such as the server address and network proxy.</p>
</td>
</tr>
<tr id="row454172810509"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p111125615215"><a name="p111125615215"></a><a name="p111125615215"></a>hpm config delete key</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p171156105215"><a name="p171156105215"></a><a name="p171156105215"></a>Deletes configurations.</p>
</td>
</tr>
<tr id="row3925233115011"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p1250314020555"><a name="p1250314020555"></a><a name="p1250314020555"></a>Updating bundle versions</p>
<p id="p59251633105018"><a name="p59251633105018"></a><a name="p59251633105018"></a></p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p1127981305516"><a name="p1127981305516"></a><a name="p1127981305516"></a>hpm update</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p427971311555"><a name="p427971311555"></a><a name="p427971311555"></a>Updates the versions of dependent bundles.</p>
</td>
</tr>
<tr id="row692503385015"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p627961317557"><a name="p627961317557"></a><a name="p627961317557"></a>hpm check-update</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p3279121315557"><a name="p3279121315557"></a><a name="p3279121315557"></a>Checks whether version updates are available to dependent bundles.</p>
</td>
</tr>
<tr id="row1925173385019"><td class="cellrowborder" rowspan="2" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p2925133305014"><a name="p2925133305014"></a><a name="p2925133305014"></a>Building</p>
<p id="p692515335501"><a name="p692515335501"></a><a name="p692515335501"></a></p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p2058919655611"><a name="p2058919655611"></a><a name="p2058919655611"></a>hpm build</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p1958920625619"><a name="p1958920625619"></a><a name="p1958920625619"></a>Builds a bundle or distribution.</p>
</td>
</tr>
<tr id="row18925233115016"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1958912618563"><a name="p1958912618563"></a><a name="p1958912618563"></a>hpm dist</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p2058936115611"><a name="p2058936115611"></a><a name="p2058936115611"></a>Packs a distribution, depending on the <strong id="b14860101202420"><a name="b14860101202420"></a><a name="b14860101202420"></a>dist</strong> script in <strong id="b1820214106247"><a name="b1820214106247"></a><a name="b1820214106247"></a>scripts</strong> of <strong id="b1589018155242"><a name="b1589018155242"></a><a name="b1589018155242"></a>bundle.json</strong>.</p>
</td>
</tr>
<tr id="row59261233155013"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p3926123305011"><a name="p3926123305011"></a><a name="p3926123305011"></a>Packing</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p1785810219574"><a name="p1785810219574"></a><a name="p1785810219574"></a>hpm pack</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p1485872165714"><a name="p1485872165714"></a><a name="p1485872165714"></a>Packs dependencies of local bundles.</p>
</td>
</tr>
<tr id="row1592653305016"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p84251810125716"><a name="p84251810125716"></a><a name="p84251810125716"></a>Burning</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p7973616175716"><a name="p7973616175716"></a><a name="p7973616175716"></a>hpm run flash</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p20973111612575"><a name="p20973111612575"></a><a name="p20973111612575"></a>Burns the firmware, depending on the <strong id="b19437163182610"><a name="b19437163182610"></a><a name="b19437163182610"></a>flash</strong> script in <strong id="b4343143492610"><a name="b4343143492610"></a><a name="b4343143492610"></a>scripts</strong> of <strong id="b14598153712617"><a name="b14598153712617"></a><a name="b14598153712617"></a>bundle.json</strong>.</p>
</td>
</tr>
<tr id="row992615339504"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p1225172310576"><a name="p1225172310576"></a><a name="p1225172310576"></a>Publishing</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p198081455105712"><a name="p198081455105712"></a><a name="p198081455105712"></a>hpm publish</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p880885516574"><a name="p880885516574"></a><a name="p880885516574"></a>Publishes a bundle, which must be unique in the repository and has a unique version. (An account is required for login.)</p>
</td>
</tr>
<tr id="row5926333135014"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p39267336504"><a name="p39267336504"></a><a name="p39267336504"></a>Running extended commands</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p9933172588"><a name="p9933172588"></a><a name="p9933172588"></a>hpm run</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p18933476584"><a name="p18933476584"></a><a name="p18933476584"></a>Runs the commands in <strong id="b15533934193012"><a name="b15533934193012"></a><a name="b15533934193012"></a>scripts</strong> defined in <strong id="b13594023013"><a name="b13594023013"></a><a name="b13594023013"></a>bundle.json</strong>. Multiple commands can be executed in batches by using <strong id="b118071346143019"><a name="b118071346143019"></a><a name="b118071346143019"></a>&amp;&amp;</strong>.</p>
</td>
</tr>
<tr id="row122864915206"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p1529124912207"><a name="p1529124912207"></a><a name="p1529124912207"></a>Generating a key</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p9291492204"><a name="p9291492204"></a><a name="p9291492204"></a>hpm gen-keys</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p429249182012"><a name="p429249182012"></a><a name="p429249182012"></a>Generates a public-private key pair and configures the public key on the HPM server, achieving password-free <strong id="b139191811163315"><a name="b139191811163315"></a><a name="b139191811163315"></a>hpm-cli</strong> login for bundle publishing.</p>
</td>
</tr>
<tr id="row3556450102011"><td class="cellrowborder" valign="top" width="20.95209520952095%" headers="mcps1.2.4.1.1 "><p id="p35561850172015"><a name="p35561850172015"></a><a name="p35561850172015"></a>Generating third-party open source notice</p>
</td>
<td class="cellrowborder" valign="top" width="30.623062306230626%" headers="mcps1.2.4.1.2 "><p id="p1155625018209"><a name="p1155625018209"></a><a name="p1155625018209"></a>hpm gen-notice</p>
</td>
<td class="cellrowborder" valign="top" width="48.42484248424842%" headers="mcps1.2.4.1.3 "><p id="p11557175015205"><a name="p11557175015205"></a><a name="p11557175015205"></a>Generates a joint file describing the notice on third-party open source based on the description of each bundle.</p>
</td>
</tr>
</tbody>
</table>
# Bundle Version<a name="EN-US_TOPIC_0000001051612092"></a>
- [Version Number Naming Specifications](#section16893854141310)
- [Version Publishing](#section43401320171420)
## Version Number Naming Specifications<a name="section16893854141310"></a>
Each version name allows only lowercase letters, which can be separated by hyphens \(-\) or underscores \(\_\). For example, **bundle** and **my\_bundle** are allowed.
A bundle version number is in the format of _major version number_._minor version number_._revision version number_ or _major version number_._minor version number_._revision version number_-_pre-release version number_, for example, **1.0.0** and **1.0.0-beta**. For details, see [https://semver.org](https://semver.org/).
## Version Publishing<a name="section43401320171420"></a>
You should upload bundles to the remote repository so that your peers have an option to use them. You can run the following command to upload the bundles:
```
hpm publish
```
After this command is executed, the system checks the bundle dependencies and downloads the missing dependencies. If the bundles you uploaded are in binary, the system compiles the entire bundle, generates a binary file, packs the file, and uploads it. If the bundles you uploaded are in another format, the system packs the bundle file in compliance with the defined packing rules and then uploads the file.
Note: To publish a bundle, you need an HPM account for login. After logging in to the HPM platform, register with an organization and apply for authentication. After successful authentication, you will have the permission to publish the bundle.
# Development Example<a name="EN-US_TOPIC_0000001072143838"></a>
This following uses the Hi3861 platform as an example to describe how to install, compile, and package components by using HPM.
1. Run the following commands to initialize the installation directory \(whose name can be customized\):
```
mkdir test3861
cd test3861
hpm init -t dist
```
If the following information is displayed, the initialization is successful:
```
Initialization finished.
```
2. Run the following command to install the **wifi\_iot** distribution:
```
hpm install @ohos/wifi_iot
```
If the following information is displayed, the installation is successful:
```
Installed.
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Run the following command for the Hi3516 platform:
>```
>hpm install @ohos/ip_camera_hi3516dv300
>```
>Run the following command for the Hi3518 platform:
>```
>hpm install @ohos/ip_camera_hi3518ev300
>```
3. Run the following command to build and package components:
```
hpm dist
```
If the building is successful, the following information is displayed:
```
{{name}}: distribution building completed.
```
4. Check the result in the **./out** directory. You can burn the distribution into the corresponding development board for testing.
# Preparations<a name="EN-US_TOPIC_0000001071315859"></a>
- [Linux Server](#section20979554791)
- [Node.js](#section9954105413153)
- [HPM](#section15937194904819)
- [Python Environment](#section1621819180417)
- [File Packaging Tool](#section77617165913)
- [SCons](#section20558439191516)
## Linux Server<a name="section20979554791"></a>
Prepare a 64-bit Linux server running Ubuntu 16.04 or later. HPM supports Windows Server, but the open-source Hi3861, Hi3516, and Hi3518 solutions support only Ubuntu.
Configure Ubuntu to use bash as the Linux system shell, by performing the following:
```
ls -l $(which sh)
# If the file does not point to bash, modify the file using either of the provided methods.
# Method 1: Run the following command and select no:
dpkg-reconfigure dash
# Method 2: Run the following commands to delete /bin/sh and then create a new symbolic link to bash:
rm -f /bin/sh
ln -s bash /bin/sh
```
## Node.js<a name="section9954105413153"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the Node.js version of the source is outdated, run the following command before running **apt-get install**:
>```
>curl -L https://deb.nodesource.com/setup_12.x | bash
>```
You are advised to install Node.js 12.x \(including npm 6.14.4\) or a later version \(12.13.0 or later is recommended\).
```
sudo apt-get install nodejs
sudo apt-get install npm
```
Run the following commands to view Node.js and NPM versions:
```
node --version # Check the Node.js version.
npm --version # Check the NPM version.
```
## HPM<a name="section15937194904819"></a>
Install the **hpm-cli** command line tool by using the NPM \(default source: https://registry.npmjs.org/\) provided by the Node.js.
```
npm install -g @ohos/hpm-cli
```
After **hpm-cli** is installed, run the following command to view default HPM configurations:
```
hpm config
```
You can modify the default configurations as required. The following lists common HPM configurations:
```
registry = https://hpm.harmonyos.com # Register with the HPM registration center. This is mandatory for downloading components.
strictSsl = true # Enable strict SSL verification as HTTPS is used for connection.
http_proxy = http://your-proxy-server:port # Configure the HTTP proxy.
https_proxy = http://your-proxy-server:port # Configure the HTTPS proxy.
```
For details about **hpm-cli** commands, see [HPM Commands](bundles-standard-rules.md).
## Python Environment<a name="section1621819180417"></a>
Run the following commands to install Python later than 3.7:
```
sudo apt-get install python3.8
sudo apt-get install python3-pip
sudo pip3 install setuptools
sudo pip3 install kconfiglib # Install kconfiglib 13.2.0 or later.
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The preceding method is applicable to Hi3518 and Hi3516 platforms. For Hi3861, run the following commands to install the Python environment:
>```
>sudo apt-get install python3.8
>sudo apt-get install python3-pip
>sudo pip3 install setuptools
>sudo pip3 install kconfiglib # Install kconfiglib 13.2.0 or later.
>sudo pip3 install pycryptodome
>sudo pip3 install six --upgrade --ignore-installed six
>sudo pip3 install ecdsa
>```
If both Python2 and Python3 have been installed in the current system, run the following commands to set the default Python to Python3:
```
ll `which python`
rm /usr/bin/python
ln -s python3.8 /usr/bin/python
```
## File Packaging Tool<a name="section77617165913"></a>
Run the following commands to install the tool:
```
which mkfs.vfat # If mkfs.vfat is not found, run the following command:
sudo apt-get install dosfstools
which mcopy # If mcopy is not found, run the following command:
sudo apt-get install mtools
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Both Hi3518 and Hi3516 platforms require the file packaging tool. For Hi3861, the tool is not required.
## SCons<a name="section20558439191516"></a>
1. Start a Linux server.
2. Run the following command to install the SCons installation package:
```
python3 -m pip install scons
```
3. Run the following command to check whether SCons is successfully installed. If the installation is successful, the query result as shown in [Figure 1](#fig235815252492) is displayed.
```
scons -v
```
**Figure 1** Successful installation \(SCons version requirement: 3.0.4 or later\)<a name="fig235815252492"></a>
![](figure/successful-installation-(scons-version-requirement-3-0-4-or-later)-25.png "successful-installation-(scons-version-requirement-3-0-4-or-later)-25")
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>SCons is required for the Hi3861 platform, but not for the Hi3518 or Hi3516 platform.
# HPM User Guide<a name="EN-US_TOPIC_0000001157479397"></a>
- **[Introduction](bundles-demo-hpmdescription.md)**
- **[Preparations](bundles-demo-environment.md)**
- **[Development Example](bundles-demo-devsample.md)**
# Bundle Development<a name="EN-US_TOPIC_0000001051690861"></a>
- [Developing OpenHarmony Bundles](#section1976410130540)
- [Creating a Bundle](#section717481119145)
- [Modifying a Bundle](#section102861955201410)
- [Using HPM-provided Template to Create a Bundle](#section15882846181510)
- [Building a Bundle](#section136732148541)
- [Defining the Building Script](#section10274147111610)
- [Executing the Building Script](#section879301916172)
- [Defining a Distribution](#section413216495619)
- [Defining Scripts](#section11503171219190)
- [Distributing](#section4694125521912)
- [Burning](#section1746331545413)
- [Debugging](#section6742131615549)
## Developing OpenHarmony Bundles<a name="section1976410130540"></a>
You have an option to use any of the following methods to develop OpenHarmony bundles:
- Develop a brand new bundle from scratch.
- Rewrite code of an existing non-bundle to develop a bundle.
- Use HPM-provided bundle templates to quickly develop a bundle.
## Creating a Bundle<a name="section717481119145"></a>
Generally, you can find commonly used bundles on the [HPM](https://hpm.harmonyos.com/#/en/home) website. If they cannot meet your requirements, you can develop your own bundles.
You can publish bundles in the HPM repository if you like, so that your peers have an option to use them. Assume that you want to create a bundle named **my-bundle** in the **D:/source** directory:
Run the **hpm init** command to create the scaffold code for this bundle. For example, you can go to the **D:/source** directory and run the following command:
```
hpm init -t default -d demo my-bundle
```
The following files are generated in the **source** directory:
```
mybundle
├── bundle.json # Metadata description file of the bundle
├── example # Example of testing bundle functions
│ └── main.c
├── include # Internal header files of the bundle
│ └── mybundle.h
├── README.md # Brief description of the bundle
└── src # Source code of the bundle
└─ mybundle.c
```
Then, complete your coding based on service requirements. Finally, use **git** to commit your code \(including the **bundle.json** file\) to the code hosting repository, such as gitee.
## Modifying a Bundle<a name="section102861955201410"></a>
If you have code unqualified for the OpenHarmony bundle structure, modify your code to match an HPM bundle. In the code directory \(for example, **mybundle2**\) storing your code, run the following command with the bundle name and version specified:
```
hpm init
```
1. Enter a bundle name \(**mybundle2** as an example\) and press **Enter**.
2. Enter the bundle version \(**1.0.0** as an example\) and press **Enter**. A **bundle.json** file is generated in the current bundle directory.
3. Add other descriptions in **bundle.json**, which is publishable.
```
$ hpm init
Your bundle will be created in dirname E:\demo\mybundle2
? bundle name mybundel2
? version 1.0.0
Init finished!
```
1. Modify other information \(such as the author, code repository, code directory, command script, and dependent bundles\) in **bundle.json**.
```
{
"name": "mybundle2",
"version": "1.0.0",
"publishAs": "source",
"dirs":{
".":[
"README.md"
],
"src":[
"test.c"
],
"header":[
"header/test.h"
],
"src/common":[
"src/common/foobar.txt"
]
},
"scripts": {
"build": "make -${args}"
},
"dependencies": {
"@ohos/cjson": "^1.0.0",
"@ohos/": "^1.2.0"
}
}
```
## Using HPM-provided Template to Create a Bundle<a name="section15882846181510"></a>
The HPM provides **default** and **simple** templates as well as other templates that are stored on the server.
You can run the **hpm search -t template** command to search for a template stored on the server.
![](figure/en-us_image_0000001051452177.png)
Then, select your desired template based on the information below **description**, use the selected template to quickly create the bundle scaffold, and run the following command with the **-t** and **-d** parameters specified:
```
hpm init -t {templatename} -d dir name
```
- **\{templatename\}** indicates the template name.
- **dir** indicates the path for storing the bundle to be created.
- **name** indicates the name of the bundle to be created.
## Building a Bundle<a name="section136732148541"></a>
After completing code development, you need to build the bundle. The HPM supports command integration so that you can select any build tool \(such as **make**, **gcc**, and **gn**\) suitable for your project. You only need to define the **build** command in the **scripts** in the **bundle.json** file of your project, and then you run the hpm command **build** to perform building.
## Defining the Building Script<a name="section10274147111610"></a>
This section uses how to build an executable file **helloworld** in the **app** directory as an example.
```
app
├── BUILD.gn
├── include
│ └── helloworld.h
└── src
└── helloworld.c
```
Create a **BUILD.gn** file in the same directory as **helloworld.c**.
```
touch BUILD.gn
vim BUILD.gn
```
The following is an example of **BUILD.gn** for your reference:
```
executable("hello_world") {
sources = [
"src/helloworld.c"
]
include_dirs = [
"include"
]
}
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>- **executable** is a built-in template of **gn**. You can run the **gn help executable** command to view how to use this template.
>- **sources** represents the source code path, and **include\_dirs** represents the header file path.
## Executing the Building Script<a name="section879301916172"></a>
Run the following command:
```
hpm build
```
After all building operations are complete, the message "build succeed" is displayed. You need to check the building result.
![](figure/en-us_image_0000001051770876.png)
## Defining a Distribution<a name="section413216495619"></a>
A distribution refers to an image file of an executable OpenHarmony solution composed of a group of bundles. It contains many dependent bundles and provides scripts to illustrate how to compile and link these bundles.
## Defining Scripts<a name="section11503171219190"></a>
Define scripts in **bundle.json** as follows:
```
{
"name": "my_dist",
"version": "1.0.0",
"publishAs": "distribution",
"scripts": {
"dist": "make -${args}"
},
"base": {
"name": "dist-bundle",
"version": "1.0.0"
},
"envs": {
"args": "x86"
},
"dependencies": {
}
}
```
## Distributing<a name="section4694125521912"></a>
Run the following command in the current distribution directory:
```
hpm dist
```
The **hpm-cli** tool automatically performs compiling and packing, and generates an image file of the **dist** script defined based on **scripts**. The following is an example:
```
out
|-xxdist.img
|-xx.file
```
## Burning<a name="section1746331545413"></a>
The building result of the distribution can be burnt into devices, for example, by using the **hiburn** tool. You need to configure burning parameters in the **bundle.json** file of the distribution.
```
"scripts": {
"flash": "{$DEP_HIBURN}/hiburn"
},
```
You should set burning parameters by referring to the specific guide on the burning tool you use.
```
hpm run flash
```
## Debugging<a name="section6742131615549"></a>
Start debugging after you have burnt the image file of the distribution into devices. The debugging process varies according to specific development boards and IDE debugging tools.
# Bundle Development<a name="EN-US_TOPIC_0000001051452100"></a>
- [Overview](#section112136415486)
- [Preparations](#section12731192104816)
- [Hardware Requirements](#section71851750144814)
- [Installing Node.js and the hpm-cli Tool](#section675199493)
- [\(Optional\) Modifying HPM Configurations](#section1940205015499)
- [Downloading OpenHarmony Code](#section42591118155217)
- [Installing Dependent Bundles](#section644212530524)
- [Bundle Development](#section15640113715318)
## Overview<a name="section112136415486"></a>
This document describes how to develop OpenHarmony bundles and distributions, and how to create, develop, and build code, as well as burn and debug devices by using a command line tool.
- A bundle usually maps onto a code repository, which is a code archive with the **bundle.json**, **README**, and **LICENSE** files.
- A distribution consists of multiple bundles. Each distribution integrates various bundles of a comprehensive system, such as the driver, kernel, framework, and applications. These bundles can be used for device burning.
**Table 1** Differences between a bundle and a distribution
<a name="table6287133615412"></a>
<table><thead align="left"><tr id="row17288183614415"><th class="cellrowborder" valign="top" width="16.24162416241624%" id="mcps1.2.4.1.1"><p id="p528818361545"><a name="p528818361545"></a><a name="p528818361545"></a>Aspect</p>
</th>
<th class="cellrowborder" valign="top" width="33.31333133313331%" id="mcps1.2.4.1.2"><p id="p1288836247"><a name="p1288836247"></a><a name="p1288836247"></a>Bundle</p>
</th>
<th class="cellrowborder" valign="top" width="50.44504450445044%" id="mcps1.2.4.1.3"><p id="p112885362418"><a name="p112885362418"></a><a name="p112885362418"></a>Distribution</p>
</th>
</tr>
</thead>
<tbody><tr id="row1728813361848"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p2010613564815"><a name="p2010613564815"></a><a name="p2010613564815"></a>Application scenario</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1910555184818"><a name="p1910555184818"></a><a name="p1910555184818"></a>Feature-oriented</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p13871955484"><a name="p13871955484"></a><a name="p13871955484"></a>System-oriented</p>
</td>
</tr>
<tr id="row676745614472"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p1028816365414"><a name="p1028816365414"></a><a name="p1028816365414"></a>Content</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p428812361042"><a name="p428812361042"></a><a name="p428812361042"></a>Codes or a binary library for implementing features</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p328817366417"><a name="p328817366417"></a><a name="p328817366417"></a>List of dependent bundles as well as their compiling and building scripts</p>
</td>
</tr>
<tr id="row95114356"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p184894513517"><a name="p184894513517"></a><a name="p184894513517"></a>Integrity</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1951741155"><a name="p1951741155"></a><a name="p1951741155"></a>A part of the operating system</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p20521542512"><a name="p20521542512"></a><a name="p20521542512"></a>An entire operating system</p>
</td>
</tr>
<tr id="row13581419518"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p859171059"><a name="p859171059"></a><a name="p859171059"></a>Compilation result</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p259201355"><a name="p259201355"></a><a name="p259201355"></a>Bundles</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p459414519"><a name="p459414519"></a><a name="p459414519"></a>System image</p>
</td>
</tr>
</tbody>
</table>
**Figure 1** Composition of bundles and distributions<a name="fig85033524124"></a>
![](figure/组件0924.png)
## Preparations<a name="section12731192104816"></a>
### Hardware Requirements<a name="section71851750144814"></a>
- Development boards \(examples: Hi3861, Hi3516D V300, and Hi3518E V300\)
- Host computer \(Windows workstation\)
- Linux server
**Figure 2** Hardware connections<a name="fig113816181847"></a>
![](figure/hardware-connections-23.png "hardware-connections-23")
### Installing **Node.js** and the **hpm-cli** Tool<a name="section675199493"></a>
1. Install **Node.js**.
Download **Node.js** from its official website and install it on your local PC.
You are advised to install [Node.js](https://nodejs.org/) 12.x \(including npm 6.14.4\) or a later version \(12.13.0 or later is recommended\).
2. Install the **hpm-cli** tool using **npm** delivered with **Node.js**. Run the following command:
```
npm install -g @ohos/hpm-cli
```
3. Run the following command to check whether the installation is successful. If an HPM version is displayed, the installation is successful.
```
hpm -V or hpm --version
```
4. \(Optional\) Run the following command to upgrade the HPM version if needed:
```
npm update -g @ohos/hpm-cli
```
### \(Optional\) Modifying HPM Configurations<a name="section1940205015499"></a>
After the **hpm-cli** tool is installed, run the following command to view HPM configurations:
```
hpm config
```
Default HPM configurations are displayed upon the command execution. You can modify the default configurations as required. The following lists common HPM configurations:
```
registry = https://hpm.harmonyos.com/hpm/registry/api # Configure the address of the HPM registry (mandatory for downloading bundles).
login = https://hpm.harmonyos.com/hpm/auth/pk # Configure the address for HPM login (mandatory for publishing bundles).
loginUser = {your-account} # Configure the account for HPM login (mandatory for publishing bundles).
shellPath = C:\WINDOWS\System32\cmd.exe # Configure the shell for running HPM commands.
globalRepo = C:\Users\yourname\.global # Configure the path for storing bundles that are installed globally.
http_proxy = http://your-proxy-server:port # Configure the HTTP proxy.
https_proxy = http://your-proxy-server:port # Configure the HTTPS proxy.
```
For details about **hpm-cli** commands, see [HPM Commands](bundles-guide-overview.md).
### Downloading OpenHarmony Code<a name="section42591118155217"></a>
For details, see [Source Code Acquisition](../get-code/sourcecode-acquire.md).
### Installing Dependent Bundles<a name="section644212530524"></a>
The HPM publishes commonly used development tools \(such as those for burning, compiling, and compression\) as bundles. You can run the following command to install these tools. After the command is executed, the system automatically downloads and installs the tools, which need to be installed globally only once.
```
hpm i -g @ohos/llvm
hpm i -g @ohos/ninja
hpm i -g @ohos/gn
hpm i -g @ohos/hc_gen
hpm i -g @ohos/sysroot
```
These are a set of development tools \(such as **gn** and **ninja**\). With these tools, you can start your general bundle development based on source code.
## Bundle Development<a name="section15640113715318"></a>
# Preparations<a name="EN-US_TOPIC_0000001051770836"></a>
- [Hardware Requirements](#section98535485518)
- [Installing Node.js and the hpm-cli Tool](#section106591616205311)
- [\(Optional\) Modifying HPM Configurations](#section71821165412)
- [Downloading OpenHarmony Code](#section102338221707)
- [Installing Dependent Bundles](#section19233183315020)
## Hardware Requirements<a name="section98535485518"></a>
- Development boards \(examples: Hi3861, Hi3516D V300, and Hi3518E V300\)
- Host computer \(Windows workstation\)
- Linux server
**Figure 1** Hardware connections<a name="fig113816181847"></a>
![](figure/hardware-connections-24.png "hardware-connections-24")
## Installing **Node.js** and the **hpm-cli** Tool<a name="section106591616205311"></a>
1. Install **Node.js**.
Download **Node.js** from its official website and install it on your local PC.
You are advised to install [Node.js](https://nodejs.org/) 12.x \(including npm 6.14.4\) or a later version \(12.13.0 or later is recommended\).
2. Install the **hpm-cli** tool using **npm** delivered with **Node.js**. Run the following command:
```
npm install -g @ohos/hpm-cli
```
3. Run the following command to check whether the installation is successful. If an HPM version is displayed, the installation is successful.
```
hpm -V or hpm --version
```
4. \(Optional\) Run the following command to upgrade the HPM version if needed:
```
npm update -g @ohos/hpm-cli
```
## \(Optional\) Modifying HPM Configurations<a name="section71821165412"></a>
After the **hpm-cli** tool is installed, run the following command to view HPM configurations:
```
hpm config
```
Default HPM configurations are displayed upon the command execution. You can modify the default configurations as required. The following lists common HPM configurations:
```
registry = https://hpm.harmonyos.com/hpm/registry/api # Configure the address of the HPM registry, mandatory for downloading bundles.
login = https://hpm.harmonyos.com/hpm/auth/pk # Configure the address for HPM login, mandatory for publishing bundles.
loginUser = {your-account} # Configure the account for HPM login, mandatory for publishing bundles.
shellPath = C:\WINDOWS\System32\cmd.exe # Configure the shell for running HPM commands.
globalRepo = C:\Users\yourname\.global # Configure the path for storing bundles that are installed globally.
http_proxy = http://your-proxy-server:port # Configure the HTTP proxy.
https_proxy = http://your-proxy-server:port # Configure the HTTPS proxy.
```
For details about **hpm-cli** commands, see [HPM Commands](bundles-guide-overview.md).
## Downloading OpenHarmony Code<a name="section102338221707"></a>
For details, see [Source Code Acquisition](../get-code/sourcecode-acquire.md).
## Installing Dependent Bundles<a name="section19233183315020"></a>
The HPM publishes commonly used development tools \(such as those for burning, compiling, and compression\) as bundles. You can run the following command to install these tools. After the command is executed, the system automatically downloads and installs the tools, which need to be installed globally only once.
```
hpm i -g @ohos/llvm
hpm i -g @ohos/ninja
hpm i -g @ohos/gn
hpm i -g @ohos/hc_gen
hpm i -g @ohos/sysroot
```
These are a set of development tools \(such as **gn** and **ninja**\). With these tools, you can start your general bundle development based on source code.
# Development Guidelines<a name="EN-US_TOPIC_0000001157319417"></a>
- **[Bundle Development](bundles-guide-overview.md)**
- **[Preparations](bundles-guide-prepare.md)**
- **[Bundle Development](bundles-guide-develop.md)**
此差异已折叠。
# Bundle Development<a name="EN-US_TOPIC_0000001111039520"></a>
- **[Development Specifications](bundles-standard-rules.md)**
- **[Development Guidelines](bundles-guide.md)**
- **[HPM User Guide](bundles-demo.md)**
# Development Example<a name="EN-US_TOPIC_0000001072143838"></a>
This following uses the Hi3861 platform as an example to describe how to install, compile, and package components by using HPM.
1. Run the following commands to initialize the installation directory \(whose name can be customized\):
```
mkdir test3861
cd test3861
hpm init -t dist
```
If the following information is displayed, the initialization is successful:
```
Initialization finished.
```
2. Run the following command to install the **wifi\_iot** distribution:
```
hpm install @ohos/wifi_iot
```
If the following information is displayed, the installation is successful:
```
Installed.
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>Run the following command for the Hi3516 platform:
>```
>hpm install @ohos/ip_camera_hi3516dv300
>```
>Run the following command for the Hi3518 platform:
>```
>hpm install @ohos/ip_camera_hi3518ev300
>```
3. Run the following command to build and package components:
```
hpm dist
```
If the building is successful, the following information is displayed:
```
{{name}}: distribution building completed.
```
4. Check the result in the **./out** directory. You can burn the distribution into the corresponding development board for testing.
# Development Guidelines<a name="EN-US_TOPIC_0000001157319417"></a>
- **[Overview](overview-0.md)**
- **[Preparations](preparations.md)**
- **[Bundle Development](bundle-development.md)**
# Development Specifications<a name="EN-US_TOPIC_0000001111199436"></a>
- **[Overview](overview.md)**
- **[Bundle Composition](bundle-composition.md)**
- **[Bundle Management](bundle-management.md)**
- **[Bundle Version](bundle-version.md)**
- **[Distribution](distribution.md)**
- **[Environment Variables](environment-variables.md)**
# Distribution<a name="EN-US_TOPIC_0000001051770842"></a>
A distribution refers to an image file of an executable OpenHarmony solution composed of a group of bundles. It contains many dependent bundles and provides scripts to illustrate how to compile and link these bundles.
Generally, a distribution does not require code but contains only the **bundle.json** description \(**publishAs** set to **distribution**\) and some compilation scripts.
As system-provided environment variables are required during distribution compiling, run the **dist** command in **scripts**.
```
{
"publishAs":"distribution",
"scripts": {
"dist": "script compile command"
}
}
```
Run the following command:
```
hpm dist
```
As it is rather complex to redefine the functionality of a distribution, OpenHarmony allows inheritance from a distribution so that you can make a tailored distribution based on the existing functionality. To inherit from a distribution, you need to define the **base** field in **bundle.json**.
```
{
"base": {
"name": "dist_wifi_iot",
"version": "1.0.0"
}
}
```
In this example, the current bundle inherits from the **dist-wifi-iot 1.0.0** bundle of the distribution.
Each distribution consists of many dependent bundles, which are represented by the **dependencies** field in **bundle.json**. Some dependencies are mandatory, and others can be added or removed required. In the **bundle.json** file, bundle names prefixed with a question mark \(?\) represent optional dependent bundles. If you want to inherit from a distribution involving such bundles, you can remove them and then add other bundles.
```
{
"dependencies": {
"?my_bundle": "1.0.0"
}
}
```
In this example, **my\_bundle** is an optional dependent bundle that can be removed by using the keyword "excludes".
```
{
"excludes": [ "my_bundle" ]
}
```
After **my-bundle** is removed, it will not be involved in the building process. If you forcibly remove mandatory dependent bundles, an error message will be displayed.
# Environment Variables<a name="EN-US_TOPIC_0000001054807267"></a>
During bundle compilation, system-provided environment variables are required to define the output and link the required binary files. These variables are injected into the context for executing scripts based on service requirements. Therefore, their values can be directly obtained from the scripts. Currently, there are global and fixed environment variables in the system.
Global variables are defined by the **envs** attribute in **bundle.json**. All dependent bundles can obtain the values of global variables.
```
{
"envs": {
"compileEnv": "arm"
}
}
```
Different parameters can be passed to bundles when introducing dependencies so that the compilation of dependent bundles can meet the requirements of the current bundle. The parameters defined in the dependencies can be obtained from the context for executing the corresponding scripts.
```
{
"dependencies": {
"my-bundle": {
"version": "1.0.0",
"mode": "debug"
}
}
}
```
When linking to a binary file, the bundle needs to know the file path regarding the dependencies. Therefore, the path \(as an environment variable\) is passed to the bundle for compiling.
The passed environment variable is in **DEP\__BundleName_** format, where **BundleName** indicates the name of the dependent bundle, for example, **DEP\_first-bundle**.
Tags can be defined to group dependent bundles. You can obtain the path of a group of dependent bundles based on their tag. A tag starts with a number sign \(\#\) and is defined as follows:
```
{
"dependencies": {
"#tool": {
"first-bundle": "1.0.0",
"second-bundle": "1.0.0"
},
"#drivers": {
"xx-bundle": "1.0.0",
"yy-bundle": "1.0.0"
}
}
}
```
There are two fixed environment variables:
- **DEP\_OHOS\_BUNDLES**: path of the **ohos\_bundles** folder
- **DEP\_BUNDLE\_BASE**: path of the outermost bundle
# HPM User Guide<a name="EN-US_TOPIC_0000001157479397"></a>
- **[Introduction](introduction.md)**
- **[Preparations](preparations-1.md)**
- **[Development Example](development-example.md)**
# Overview<a name="EN-US_TOPIC_0000001051452100"></a>
This document describes how to develop OpenHarmony bundles and distributions, and how to create, develop, and build code, as well as burn and debug devices by using a command line tool.
- A bundle usually maps onto a code repository, which is a code archive with the **bundle.json**, **README**, and **LICENSE** files.
- A distribution consists of multiple bundles. Each distribution integrates various bundles of a comprehensive system, such as the driver, kernel, framework, and applications. These bundles can be used for device burning.
**Table 1** Differences between a bundle and a distribution
<a name="table6287133615412"></a>
<table><thead align="left"><tr id="row17288183614415"><th class="cellrowborder" valign="top" width="16.24162416241624%" id="mcps1.2.4.1.1"><p id="p528818361545"><a name="p528818361545"></a><a name="p528818361545"></a>Aspect</p>
</th>
<th class="cellrowborder" valign="top" width="33.31333133313331%" id="mcps1.2.4.1.2"><p id="p1288836247"><a name="p1288836247"></a><a name="p1288836247"></a>Bundle</p>
</th>
<th class="cellrowborder" valign="top" width="50.44504450445044%" id="mcps1.2.4.1.3"><p id="p112885362418"><a name="p112885362418"></a><a name="p112885362418"></a>Distribution</p>
</th>
</tr>
</thead>
<tbody><tr id="row1728813361848"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p2010613564815"><a name="p2010613564815"></a><a name="p2010613564815"></a>Application scenario</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1910555184818"><a name="p1910555184818"></a><a name="p1910555184818"></a>Feature-oriented</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p13871955484"><a name="p13871955484"></a><a name="p13871955484"></a>System-oriented</p>
</td>
</tr>
<tr id="row676745614472"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p1028816365414"><a name="p1028816365414"></a><a name="p1028816365414"></a>Content</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p428812361042"><a name="p428812361042"></a><a name="p428812361042"></a>Codes or a binary library for implementing features</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p328817366417"><a name="p328817366417"></a><a name="p328817366417"></a>List of dependent bundles as well as their compiling and building scripts</p>
</td>
</tr>
<tr id="row95114356"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p184894513517"><a name="p184894513517"></a><a name="p184894513517"></a>Integrity</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1951741155"><a name="p1951741155"></a><a name="p1951741155"></a>A part of the operating system</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p20521542512"><a name="p20521542512"></a><a name="p20521542512"></a>An entire operating system</p>
</td>
</tr>
<tr id="row13581419518"><td class="cellrowborder" valign="top" width="16.24162416241624%" headers="mcps1.2.4.1.1 "><p id="p859171059"><a name="p859171059"></a><a name="p859171059"></a>Compilation result</p>
</td>
<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p259201355"><a name="p259201355"></a><a name="p259201355"></a>Bundles</p>
</td>
<td class="cellrowborder" valign="top" width="50.44504450445044%" headers="mcps1.2.4.1.3 "><p id="p459414519"><a name="p459414519"></a><a name="p459414519"></a>System image</p>
</td>
</tr>
</tbody>
</table>
**Figure 1** Composition of bundles and distributions<a name="fig85033524124"></a>
![](figures/组件0924.png)
# Overview<a name="EN-US_TOPIC_0000001051452141"></a>
- [Definition](#section177563344911)
- [Bundle Division Principles](#section2487162541016)
- [Bundle Dependency](#section185955409107)
This document describes the basic concepts of a bundle and how to define it in compliance with specifications.
## Definition<a name="section177563344911"></a>
OpenHarmony software is developed on a per-bundle basis. In terms of the operating system, all software running on OpenHarmony are bundles. Generally, bundles are classified into the following types based on their application scopes:
- Board-level bundles: device hardware-specific bundles, such as **board**, **arch**, and **mcu**
- System-level bundles: a set of bundles with independent features, such as the kernel, file system, and framework
- Application-level bundles: applications that provide services to users, such as **wifi\_iot** and **ip\_camera**
Bundles are designed for the reuse purpose. Any reusable modules can be defined as bundles. They are classified into the following types based on their forms:
- Source code
- Binary system
- Code snippet
- Distribution
## Bundle Division Principles<a name="section2487162541016"></a>
In principle, bundles should be grouped at a fine-grained granularity as much as possible to achieve maximum reuse. The following factors are taken into account regarding bundle division:
- Independence: Bundles provide relatively independent features and can be independently compiled. Each of them is capable of providing its own APIs and services for external systems.
- Coupling: If a bundle must depend on another bundle to provide services, they can be coupled to one bundle.
- Correlation: If a group of bundles jointly implement a feature, and if other bundles never depend on them, the group of bundles can be combined into one bundle.
## Bundle Dependency<a name="section185955409107"></a>
A bundle dependency can be mandatory or optional.
- Mandatory dependency: If bundle A must depend on bundle B to implement a feature, that is, the APIs or services specific to bundle B must be invoked, then bundle B is defined as the mandatory dependency of bundle A.
- Optional dependency: If either bundle C or bundle D is required for bundle A to implement a feature, and if bundle C and bundle D are interchangeable, then bundle C and bundle D are defined as optional dependencies of bundle A.
# Preparations<a name="EN-US_TOPIC_0000001071315859"></a>
- [Linux Server](#section20979554791)
- [Node.js](#section9954105413153)
- [HPM](#section15937194904819)
- [Python Environment](#section1621819180417)
- [File Packaging Tool](#section77617165913)
- [SCons](#section20558439191516)
## Linux Server<a name="section20979554791"></a>
Prepare a 64-bit Linux server running Ubuntu 16.04 or later. HPM supports Windows Server, but the open-source Hi3861, Hi3516, and Hi3518 solutions support only Ubuntu.
Configure Ubuntu to use bash as the Linux system shell, by performing the following:
```
ls -l $(which sh)
# If the file does not point to bash, modify the file using either of the provided methods.
# Method 1: Run the following command and select no:
dpkg-reconfigure dash
# Method 2: Run the following commands to delete /bin/sh and then create a new symbolic link to bash:
rm -f /bin/sh
ln -s bash /bin/sh
```
## Node.js<a name="section9954105413153"></a>
>![](public_sys-resources/icon-note.gif) **NOTE:**
>If the Node.js version of the source is outdated, run the following command before running **apt-get install**:
>```
>curl -L https://deb.nodesource.com/setup_12.x | bash
>```
You are advised to install Node.js 12.x \(including npm 6.14.4\) or a later version \(12.13.0 or later is recommended\).
```
sudo apt-get install nodejs
sudo apt-get install npm
```
Run the following commands to view Node.js and NPM versions:
```
node --version # Check the Node.js version.
npm --version # Check the NPM version.
```
## HPM<a name="section15937194904819"></a>
Install the **hpm-cli** command line tool by using the NPM \(default source: https://registry.npmjs.org/\) provided by the Node.js.
```
npm install -g @ohos/hpm-cli
```
After **hpm-cli** is installed, run the following command to view default HPM configurations:
```
hpm config
```
You can modify the default configurations as required. The following lists common HPM configurations:
```
registry = https://hpm.harmonyos.com # Register with the HPM registration center. This is mandatory for downloading components.
strictSsl = true # Enable strict SSL verification as HTTPS is used for connection.
http_proxy = http://your-proxy-server:port # Configure the HTTP proxy.
https_proxy = http://your-proxy-server:port # Configure the HTTPS proxy.
```
For details about **hpm-cli** commands, see [HPM Commands](bundle-management.md).
## Python Environment<a name="section1621819180417"></a>
Run the following commands to install Python later than 3.7:
```
sudo apt-get install python3.8
sudo apt-get install python3-pip
sudo pip3 install setuptools
sudo pip3 install kconfiglib # Install kconfiglib 13.2.0 or later.
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>The preceding method is applicable to Hi3518 and Hi3516 platforms. For Hi3861, run the following commands to install the Python environment:
>```
>sudo apt-get install python3.8
>sudo apt-get install python3-pip
>sudo pip3 install setuptools
>sudo pip3 install kconfiglib # Install kconfiglib 13.2.0 or later.
>sudo pip3 install pycryptodome
>sudo pip3 install six --upgrade --ignore-installed six
>sudo pip3 install ecdsa
>```
If both Python2 and Python3 have been installed in the current system, run the following commands to set the default Python to Python3:
```
ll `which python`
rm /usr/bin/python
ln -s python3.8 /usr/bin/python
```
## File Packaging Tool<a name="section77617165913"></a>
Run the following commands to install the tool:
```
which mkfs.vfat # If mkfs.vfat is not found, run the following command:
sudo apt-get install dosfstools
which mcopy # If mcopy is not found, run the following command:
sudo apt-get install mtools
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>Both Hi3518 and Hi3516 platforms require the file packaging tool. For Hi3861, the tool is not required.
## SCons<a name="section20558439191516"></a>
1. Start a Linux server.
2. Run the following command to install the SCons installation package:
```
python3 -m pip install scons
```
3. Run the following command to check whether SCons is successfully installed. If the installation is successful, the query result as shown in [Figure 1](#fig235815252492) is displayed.
```
scons -v
```
**Figure 1** Successful installation \(SCons version requirement: 3.0.4 or later\)<a name="fig235815252492"></a>
![](figures/successful-installation-(scons-version-requirement-3-0-4-or-later).png "successful-installation-(scons-version-requirement-3-0-4-or-later)")
>![](public_sys-resources/icon-note.gif) **NOTE:**
>SCons is required for the Hi3861 platform, but not for the Hi3518 or Hi3516 platform.
# Preparations<a name="EN-US_TOPIC_0000001051770836"></a>
- [Hardware Requirements](#section98535485518)
- [Installing Node.js and the hpm-cli Tool](#section106591616205311)
- [\(Optional\) Modifying HPM Configurations](#section71821165412)
- [Downloading OpenHarmony Code](#section102338221707)
- [Installing Dependent Bundles](#section19233183315020)
## Hardware Requirements<a name="section98535485518"></a>
- Development boards \(examples: Hi3861, Hi3516DV300, and Hi3518EV300\)
- Host computer \(Windows workstation\)
- Linux server
**Figure 1** Hardware connections<a name="fig113816181847"></a>
![](figures/hardware-connections.png "hardware-connections")
## Installing **Node.js** and the **hpm-cli** Tool<a name="section106591616205311"></a>
1. Install **Node.js**.
Download **Node.js** from its official website and install it on your local PC.
You are advised to install [Node.js](https://nodejs.org/) 12.x \(including npm 6.14.4\) or a later version \(12.13.0 or later is recommended\).
2. Install the **hpm-cli** tool using **npm** delivered with **Node.js**. Run the following command:
```
npm install -g @ohos/hpm-cli
```
3. Run the following command to check whether the installation is successful. If an HPM version is displayed, the installation is successful.
```
hpm -V or hpm --version
```
4. \(Optional\) Run the following command to upgrade the HPM version if needed:
```
npm update -g @ohos/hpm-cli
```
## \(Optional\) Modifying HPM Configurations<a name="section71821165412"></a>
After the **hpm-cli** tool is installed, run the following command to view HPM configurations:
```
hpm config
```
Default HPM configurations are displayed upon the command execution. You can modify the default configurations as required. The following lists common HPM configurations:
```
registry = https://hpm.harmonyos.com/hpm/registry/api # Configure the address of the HPM registry, mandatory for downloading bundles.
login = https://hpm.harmonyos.com/hpm/auth/pk # Configure the address for HPM login, mandatory for publishing bundles.
loginUser = {your-account} # Configure the account for HPM login, mandatory for publishing bundles.
shellPath = C:\WINDOWS\System32\cmd.exe # Configure the shell for running HPM commands.
globalRepo = C:\Users\yourname\.global # Configure the path for storing bundles that are installed globally.
http_proxy = http://your-proxy-server:port # Configure the HTTP proxy.
https_proxy = http://your-proxy-server:port # Configure the HTTPS proxy.
```
For details about **hpm-cli** commands, see [HPM Commands](bundle-management.md).
## Downloading OpenHarmony Code<a name="section102338221707"></a>
For details, see [Source Code Acquisition](../get-code/source-code-acquisition.md).
## Installing Dependent Bundles<a name="section19233183315020"></a>
The HPM publishes commonly used development tools \(such as those for burning, compiling, and compression\) as bundles. You can run the following command to install these tools. After the command is executed, the system automatically downloads and installs the tools, which need to be installed globally only once.
```
hpm i -g @ohos/llvm
hpm i -g @ohos/ninja
hpm i -g @ohos/gn
hpm i -g @ohos/hc_gen
hpm i -g @ohos/sysroot
```
These are a set of development tools \(such as **gn** and **ninja**\). With these tools, you can start your general bundle development based on source code.
# Drivers
- [HDF](hdf.md)
- [HDF Overview](hdfoverview.md)
- [Driver Development](driver-development.md)
- [Driver Service Management](driver-service-management.md)
- [Driver Message Mechanism Management](driver-message-mechanism-management.md)
- [Driver Configuration Management](driver-configuration-management.md)
- [HDF Development Example](hdfdevelopment-example.md)
- [Driver Platform](driver-platform.md)
- [GPIO](gpio.md)
- [GPIO Overview](gpiooverview.md)
- [GPIO Usage Guidelines](gpiousage-guidelines.md)
- [GPIO Usage Example](gpiousage-example.md)
- [I2C](i2c.md)
- [I2C Overview](i2c-overview.md)
- [I2C Usage Guidelines](i2c-usage-guidelines.md)
- [I2C Usage Example](i2c-usage-example.md)
- [RTC](rtc.md)
- [RTC Overview](rtc-overview.md)
- [RTC Usage Guidelines](rtc-usage-guidelines.md)
- [RTC Usage Example](rtc-usage-example.md)
- [SDIO](sdio.md)
- [SDIO Overview](sdiooverview.md)
- [SDIO Usage Guidelines](sdiousage-guidelines.md)
- [SDIO Usage Example](sdiousage-example.md)
- [SPI](spi.md)
- [SPI Overview](spioverview.md)
- [SPI Usage Guidelines](spiusage-guidelines.md)
- [SPI Usage Example](spiusage-example.md)
- [UART](uart.md)
- [UART Overview](uartoverview.md)
- [UART Usage Guidelines](uartusage-guidelines.md)
- [UART Usage Example](uartusage-example.md)
- [WATCHDOG](watchdog.md)
- [Watchdog Overview](watchdogoverview.md)
- [Watchdog Usage Guidelines](watchdogusage-guidelines.md)
- [Watchdog Usage Example](watchdogusage-example.md)
- [MIPI DSI](mipi-dsi.md)
- [MIPI DSI Overview](mipi-dsi-overview.md)
- [Usage Guidelines](usage-guidelines.md)
- [Usage Example](usage-example.md)
- [Peripherals](peripherals.md)
- [LCD](lcd.md)
- [LCD Overview](lcdoverview.md)
- [LCD Development Guidelines](lcddevelopment-guidelines.md)
- [LCD Development Example](lcddevelopment-example.md)
- [TOUCHSCREEN](touchscreen.md)
- [Touchscreen Overview](touchscreenoverview.md)
- [Touchscreen Development Guidelines](touchscreendevelopment-guidelines.md)
- [Touchscreen Development Example](touchscreendevelopment-example.md)
- [SENSOR](sensor.md)
- [Sensor Driver Overview](sensor-driver-overview.md)
- [Sensor Driver Development Guidelines](sensor-driver-development-guidelines.md)
- [Sensor Driver Development Example](sensor-driver-development-example.md)
- [Sensor Driver Test Guidelines](sensor-driver-test-guidelines.md)
- [WLAN](wlan.md)
- [WLAN Overview](wlanoverview.md)
- [WLAN Development Guidelines](wlandevelopment-guidelines.md)
- [WLAN Development Example](wlandevelopment-example.md)
# drivers
- [HDF](driver-hdf.md)
- [HDF Overview](driver-hdf-overview.md)
- [driverr Development](driver-hdf-development.md)
- [driverr Service Management](driver-hdf-servicemanage.md)
- [driverr Message Mechanism Management](driver-hdf-news.md)
- [driverr Configuration Management](driver-hdf-manage.md)
- [HDF Development Example](driver-hdf-sample.md)
- [Platform driverrs](driver-platform.md)
- [GPIO](driver-platform-gpio-des.md)
- [I2C](driver-platform-i2c-des.md)
- [RTC](driver-platform-rtc-des.md)
- [SDIO](driver-platform-sdio-des.md)
- [SPI](driver-platform-spi-des.md)
- [UART](driver-platform-uart-des.md)
- [Watchdog](driver-platform-watchdog-des.md)
- [MIPI DSI](driver-platform-mipidsi-des.md)
- [Peripherals](driver-peripherals.md)
- [LCD](driver-peripherals-lcd-des.md)
- [TOUCHSCREEN](driver-peripherals-touch-des.md)
- [Sensor](driver-peripherals-sensor-des.md)
- [WLAN](driver-peripherals-external-des.md)
\ No newline at end of file
# Driver Configuration Management<a name="EN-US_TOPIC_0000001053493462"></a>
- [HDF Configuration Overview](#section59914284576)
- [Configuration Syntax](#section533713333580)
- [Keywords](#section1316625413586)
- [Basic Syntax](#section173481622115918)
- [Data Types](#section96521601302)
- [Pre-processing](#section8164295515)
- [Commenting](#section0338205819610)
- [Modifying a Reference](#section179799204716)
- [Replicating Node Configuration](#section382424014712)
- [Deleting a Node or Attribute](#section165211112586)
- [Referencing an Attribute](#section192841514490)
- [Keyword Template](#section520134294)
- [Configuration Generation](#section106152531919)
- [Introduction to HC-GEN](#section8260625101012)
## HDF Configuration Overview<a name="section59914284576"></a>
HCS is the source code that describes the configuration of the HDF using key-value pairs. It decouples the configuration code from driver code, thereby facilitating configuration management.
HDF Configuration Generator \(HC-GEN\) is a tool for converting a configuration file into a file that can be read by the target software.
- In a low-performance system on a chip \(SoC\), this tool can convert a configuration file into the source code of the configuration tree so that the driver can obtain the configuration by directly calling the C library code.
- In a high-performance SoC, this tool can convert an HCS configuration file into the HDF Configuration Binary \(HCB\) file, allowing the driver to obtain the configuration through the APIs provided by the HDF.
The following figure shows the typical application scenario of the HCB mode.
**Figure 1** Process of using HCS<a name="fig814111371944"></a>
![](figures/en-us_image_0000001053405727.png)
The HCS is compiled using the HC-GEN tool to generate an HCB file. The HCS Parser module in the HDF recreates a configuration tree using the HCB file. Then, the HDF driver modules obtain the configurations using the API provided by the HCS Paser.
## Configuration Syntax<a name="section533713333580"></a>
The HCS syntax is described as follows:
## Keywords<a name="section1316625413586"></a>
The keywords listed in the following table below are reserved for HCS configuration files.
**Table 1** Reserved keywords for HCS configuration files
<a name="table197619515016"></a>
<table><thead align="left"><tr id="row107621651103"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p0745257902"><a name="p0745257902"></a><a name="p0745257902"></a>Keywords</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p1974510571305"><a name="p1974510571305"></a><a name="p1974510571305"></a>Description</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p10745175720020"><a name="p10745175720020"></a><a name="p10745175720020"></a>Remarks</p>
</th>
</tr>
</thead>
<tbody><tr id="row77624515014"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p8745657307"><a name="p8745657307"></a><a name="p8745657307"></a>root</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p074525719015"><a name="p074525719015"></a><a name="p074525719015"></a>Configures the root node.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1174515575018"><a name="p1174515575018"></a><a name="p1174515575018"></a>-</p>
</td>
</tr>
<tr id="row18762175115012"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p11745175710019"><a name="p11745175710019"></a><a name="p11745175710019"></a>include</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p167458577016"><a name="p167458577016"></a><a name="p167458577016"></a>References other HCS configuration files.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p9745135718012"><a name="p9745135718012"></a><a name="p9745135718012"></a>-</p>
</td>
</tr>
<tr id="row20762251608"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p16745105712015"><a name="p16745105712015"></a><a name="p16745105712015"></a>delete</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p774585716016"><a name="p774585716016"></a><a name="p774585716016"></a>Deletes a node or an attribute.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p974514571102"><a name="p974514571102"></a><a name="p974514571102"></a>This keyword applies only to the configuration tree imported using the <strong id="b2160333103716"><a name="b2160333103716"></a><a name="b2160333103716"></a>include</strong> keyword.</p>
</td>
</tr>
<tr id="row18762751509"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p174617571907"><a name="p174617571907"></a><a name="p174617571907"></a>template</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1874610571705"><a name="p1874610571705"></a><a name="p1874610571705"></a>Defines a template node.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p774617571019"><a name="p774617571019"></a><a name="p774617571019"></a>-</p>
</td>
</tr>
<tr id="row376320511903"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p3746557501"><a name="p3746557501"></a><a name="p3746557501"></a>match_attr</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1174635712015"><a name="p1174635712015"></a><a name="p1174635712015"></a>Marks the node attribute for matching.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1774615571508"><a name="p1774615571508"></a><a name="p1774615571508"></a>During configuration parsing, the keyword value can be used to find the corresponding node.</p>
</td>
</tr>
</tbody>
</table>
## Basic Syntax<a name="section173481622115918"></a>
The HCS configuration file consists of configurations of attributes and nodes.
**Attributes**
An attribute, as the minimum configuration unit, is an independent configuration item. Its syntax is as follows:
```
attribute_name = value;
```
- The value of **attribute\_name** is a case-sensitive string of characters starting with a letter and consisting of letters, digits, and underscores \(\_\).
- Available formats of **value** are as follows:
- A binary, octal, decimal, or hexadecimal integer. For details, see [Data Types](#section96521601302).
- A character string. The content should be enclosed in double quotation marks \(" "\).
- A node reference
- An attribute key-value pair must end with a semicolon \(;\) and belong to a node.
**Nodes**
A node is a set of attributes. Its syntax is as follows:
```
node_name {
module = "sample";
...
}
```
- The value of **node\_name** is a case-sensitive string of characters starting with a letter and consisting of letters, digits, and underscores \(\_\).
- A semicolon \(;\) is not required after the curly brace \(\}\).
- The reserved keyword **root** is used to declare the root node of a configuration table.
- The root node must contain a **module** attribute that uses a string to represent the module to which the configuration belongs.
- The **match\_attr** attribute can be added to a node. Its value is a globally unique character string. During configuration parsing, the query interface can be invoked to query the nodes with the attribute based on the attribute value.
## Data Types<a name="section96521601302"></a>
Attributes automatically use built-in data types, including integers, strings, arrays, and booleans. You do not need to explicitly specify the data type for the attribute values.
**Integer**
An integer can be binary, octal, decimal, or hexadecimal. The minimum space is automatically allocated to the integer based on the actual data length.
- Binary: prefixed with 0b, for example, 0b1010
- Octal: prefixed with 0, for example, 0664
- Decimal: either signed or unsigned, without a prefix, for example, 1024 or +1024. Negative integers can be read only via signed interfaces.
- Hexadecimal: prefixed with 0x, for example, 0xff00 and 0xFF
**String**
A string is enclosed by double quotation marks \(" "\).
**Array**
The elements in an array can be integers or strings, but cannot be a combination of both. The combination of **uint32\_t** and **uint64\_t** in an integer array will enable up-casting 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"];
```
**Boolean**
A Boolean data type has two possible values: **true** and **false**.
## Pre-processing<a name="section8164295515"></a>
**include**
The **include** keyword is used to import other HCS files. The syntax is as follows:
```
#include "foo.hcs"
#include "../bar.hcs"
```
- The file names must be enclosed by double quotation marks \(" "\). Files in different directories can be referenced using relative paths. The file included must be a valid HCS file.
- In the scenario that multiple HCS files are imported using **include**, if the same nodes exist, the latter node will override the former one, and other nodes are listed in sequence.
## Commenting<a name="section0338205819610"></a>
Comments can be formatted as follows:
- Single-line comment
```
// comment
```
- Multi-line comment
```
/*
comment
*/
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>Multi-line comments cannot be nested.
## Modifying a Reference<a name="section179799204716"></a>
You can use the following syntax to modify the content of any other node:
```
node :& source_node
```
This syntax indicates that the node value is a modification of the source\_node value. Example:
```
root {
module = "sample";
foo {
foo_ :& root.bar{
attr = "foo";
}
foo1 :& foo2 {
attr = 0x2;
}
foo2 {
attr = 0x1;
}
}
bar {
attr = "bar";
}
}
```
The following configuration tree is generated:
```
root {
module = "sample";
foo {
foo2 {
attr = 0x2;
}
}
bar {
attr = "foo";
}
}
```
In the preceding example, the **foo.foo\_** node changes the value of the referenced **bar.attr** to "**foo**", and the **foo.foo1** node changes the value of the referenced **foo.foo2.attr** to **0x2**. In the generated configuration tree, **foo.foo\_** and **foo.foo1** are not displayed, but their configuration modifications are presented by their referenced nodes.
- A node of the same level can be referenced simply using the node name. A node of a different level must be referenced by the absolute path, and node names are separated using a period \(.\). **root** indicates the root node. The path format is the node path sequence starting with root. For example, **root.foo.bar** is a valid absolute path.
- If multiple modifications are made to the same attribute, only one uncertain modification can take effect, and a warning will be displayed.
## Replicating Node Configuration<a name="section382424014712"></a>
The content of a node can be replicated to another node to define the node with similar content. The syntax is as follows:
```
node : source_node
```
The preceding statement indicates that the attributes of **source\_node** are replicated to **node**. Example:
```
root {
module = "sample";
foo {
attr_0 = 0x0;
}
bar:foo {
attr_1 = 0x1;
}
}
```
The following configuration tree is generated:
```
root {
module = "sample";
foo {
attr_0 = 0x0;
}
bar {
attr_1 = 0x1;
attr_0 = 0x0;
}
}
```
In the preceding example, the **bar** node configuration includes both the **attr\_0** and **attr\_1** values. The modification to **attr\_0** in the **bar** node does not affect the **foo** node.
The path of the **foo** node is not required if the **foo** node and the **bar** node are of the same level. Otherwise, the absolute path must be used. For details, see [Modifying a Reference](#section179799204716).
## Deleting a Node or Attribute<a name="section165211112586"></a>
You can use the keyword **delete** to delete unnecessary nodes or attributes in the base configuration tree imported by the **include** keyword. In the following example, **sample1.hcs** imports the configuration of **sample2.hcs** using **include**, and deletes the **attribute2** attribute and the **foo\_2** node using the **delete** keyword.
```
// sample2.hcs
root {
attr_1 = 0x1;
attr_2 = 0x2;
foo_2 {
t = 0x1;
}
}
// sample1.hcs
#include "sample2.hcs"
root {
attr_2 = delete;
foo_2 : delete {
}
}
```
The following configuration tree is generated:
```
root {
attr_1 = 0x1;
}
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>The **delete** keyword cannot be used in the same HCS file. It is recommended that you delete unnecessary attributes directly from the configuration source code.
## Referencing an Attribute<a name="section192841514490"></a>
To quickly locate the associated node during configuration parsing, you can use the node as the value of the attribute and read the attribute to find the corresponding node. The syntax is as follows:
```
attribute = &node;
```
This syntax indicates that the **attribute** value is a reference to **node**. During code parsing, you can quickly locate the node using this attribute. Example:
```
node1 {
attributes;
}
node2 {
attr_1 = &node1;
}
```
## Keyword Template<a name="section520134294"></a>
The **template** keyword is used to generate nodes with strictly consistent syntax, thereby facilitating the traverse and management of nodes of the same type.
If a node is defined using the keyword **template**, its child nodes inherit the node configuration through the double colon operator \(::\). The child nodes can modify but cannot add or 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";
template foo {
attr_1 = 0x1;
attr_2 = 0x2;
}
bar :: foo {
}
bar_1 :: foo {
attr_1 = 0x2;
}
}
```
The following configuration tree is generated:
```
root {
module = "sample";
bar {
attr_1 = 0x1;
attr_2 = 0x2;
}
bar_1 {
attr_1 = 0x2;
attr_2 = 0x2;
}
}
```
In the preceding example, the **bar** and **bar\_1** nodes inherit the **foo** node. The structures of the generated configuration tree nodes are the same as that of the **foo** node, but the attribute values are different.
## Configuration Generation<a name="section106152531919"></a>
The HC-GEN tool is used to generate configurations. It checks the HCS configuration syntax and converts HCS source files into HCB files.
## Introduction to HC-GEN<a name="section8260625101012"></a>
Parameter description:
```
Usage: hc-gen [Options] [File]
options:
-o <file> output file name, default same as input
-a hcb align with four bytes
-b output binary output, default enable
-t output config in C language source file style
-i output binary hex dump in C language source file style
-p <prefix> prefix of generated symbol name
-d decompile hcb to hcs
-V show verbose info
-v show version
-h show this help message
```
Generate a **.c** or **.h** configuration file.
```
hc-gen -o [OutputCFileName] -t [SourceHcsFileName]
```
Generate an HCB file.
```
hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName]
```
Compile an **HCB** file to an **HCS** file:
```
hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName]
```
# Driver Development<a name="EN-US_TOPIC_0000001051930361"></a>
- [Introduction](#section157425168112)
- [How to Develop](#section1969312275533)
## Introduction<a name="section157425168112"></a>
The HDF is designed based on the component-based driver model. It provides more refined driver management to make driver development and deployment more standard. 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. The following figure shows the HDF driver management model.
**Figure 1** HDF driver management model<a name="fig5487113011526"></a>
![](figures/en-us_image_0000001054564784.png)
## How to Develop<a name="section1969312275533"></a>
Driver development based on the HDF consists of two parts: driver implementation and driver configuration. The details are as follows:
1. <a name="li35182436435"></a>Implement driver.
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.
#include "hdf_log.h" // Header file of the log interface provided by the HDF.
#define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If the tag is not specified, HDF_TAG is used by default.
// 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);
```
2. Compile the driver code.
- Use the **Makefile** template provided by the HDF to compile the driver code.
```
include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk # (Mandatory) Import the predefined content of the HDF.
MODULE_NAME := # Generated result file
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 template Makefile to complete compilation.
```
- Link the compilation result file to the kernel image by adding the result file to **hdf\_vendor.mk** in the **vendor** directory. The following is an example:
```
LITEOS_BASELIB += -lxxx # Static library generated through linking
LIB_SUBDIRS += # Directory of Makefile
```
3. Configure the driver.
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-configuration-management.md).
The driver configuration consists of the driver device description defined by the HDF and private driver configuration information.
- \(Mandatory\) Driver device description
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:
```
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 = "";
priority = 100;
template device {
template deviceNode {
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
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.
device_sample :: device { // Device node of sample
device0 :: deviceNode { // DeviceNode of the sample driver
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.
preload = 0; // On-demand driver loading. For details, see "NOTE" at the end of this section.
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.
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.
}
}
}
}
}
```
- \(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"
```
>![](public_sys-resources/icon-note.gif) **NOTE:**
>On-demand loading and sequential loading are supported. The detailed usage is as follows:
>- On-demand loading
> ```
> typedef enum {
> DEVICE_PRELOAD_ENABLE = 0,
> DEVICE_PRELOAD_ENABLE_STEP2,
> DEVICE_PRELOAD_DISABLE,
> DEVICE_PRELOAD_INVALID
> } DevicePreload;
> ```
> When the **preload** field in the configuration file is set to **0** \(**DEVICE\_PRELOAD\_ENABLE**\), the driver is loaded by default during system startup. When this field is set to **1** \(**DEVICE\_PRELOAD\_ENABLE\_STEP2**\), the driver is loaded after system startup if quick start is enabled; it is loaded during system startup otherwise. When this field is set to **2** \(**DEVICE\_PRELOAD\_DISABLE**\), the driver is not loaded by default during system startup and can be dynamically loaded later. If the driver service does not exist when a user-level application obtains the driver service \(for details about how to obtain the driver service, see [Driver Message Mechanism Management](driver-message-mechanism-management.md)\), the HDF attempts to dynamically load the driver.
>- 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.
# Driver Development<a name="EN-US_TOPIC_0000001051930361"></a>
- [Introduction](#section157425168112)
- [How to Develop](#section1969312275533)
## Introduction<a name="section157425168112"></a>
The HDF is designed based on the component-based driver model. It provides more refined driver management to make driver development and deployment more standard. 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](#fig5487113011526) shows the HDF driver model.
**Figure 1** HDF driver model<a name="fig5487113011526"></a>
![](figure/en-us_image_0000001054564784.png)
## How to Develop<a name="section1969312275533"></a>
Driver development based on the HDF consists of two parts: driver implementation and driver configuration. The details are as follows:
1. <a name="li35182436435"></a>Implement driver.
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.
#include "hdf_log.h" // Header file that describes 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.
// 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);
```
2. Compile the driver code.
- Use the **Makefile** template provided by the HDF to compile the driver code.
```
include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk # (Mandatory) Import the predefined content of the HDF.
MODULE_NAME := # Generated result file
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 template Makefile to complete compilation.
```
- Link the compilation result file to the kernel image by adding the result file to **hdf\_vendor.mk** in the **vendor** directory. The following is an example:
```
LITEOS_BASELIB += -lxxx # Static library generated through linking
LIB_SUBDIRS += # Directory of Makefile
```
3. Configure the driver.
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).
The driver configuration consists of the driver device description defined by the HDF and private driver configuration information.
- \(Mandatory\) Driver device description
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:
```
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 = "";
priority = 100;
template device {
template deviceNode {
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
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.
device_sample :: device { // Device node of sample
device0 :: deviceNode { // DeviceNode of the sample driver
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.
preload = 0; // On-demand loading of the driver. For details, see "NOTE" at the end of this section.
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.
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.
}
}
}
}
}
```
- \(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"
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>On-demand loading and sequential loading are supported. The detailed usage is as follows:
>- On-demand loading
> ```
> typedef enum {
> DEVICE_PRELOAD_ENABLE = 0,
> DEVICE_PRELOAD_ENABLE_STEP2,
> DEVICE_PRELOAD_DISABLE,
> DEVICE_PRELOAD_INVALID
> } DevicePreload;
> ```
> When the **preload** field in the configuration file is set to **0** \(**DEVICE\_PRELOAD\_ENABLE**\), the driver is loaded by default during system startup. When this field is set to **1** \(**DEVICE\_PRELOAD\_ENABLE\_STEP2**\), the driver is loaded after system startup if quick start is enabled; it is loaded during system startup otherwise. When this field is set to **2** \(**DEVICE\_PRELOAD\_DISABLE**\), the driver is not loaded by default during system startup and can be dynamically loaded later. If the driver service does not exist when a user-level application obtains the driver service \(for details about how to obtain the driver service, see [Driver Message Mechanism Management](drive-hdf-news.md)\), the HDF attempts to dynamically load the driver.
>- 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.
# Driver Configuration Management<a name="EN-US_TOPIC_0000001053493462"></a>
- [HDF Configuration Overview](#section59914284576)
- [Configuration Syntax](#section533713333580)
- [Keywords](#section1316625413586)
- [Basic Syntax](#section173481622115918)
- [Data Types](#section96521601302)
- [Pre-processing](#section8164295515)
- [Commenting](#section0338205819610)
- [Modifying a Reference](#section179799204716)
- [Replicating Node Configuration](#section382424014712)
- [Deleting a Node or Attribute](#section165211112586)
- [Referencing an Attribute](#section192841514490)
- [Keyword Template](#section520134294)
- [Configuration Generation](#section106152531919)
- [Introduction to HC-GEN](#section8260625101012)
## HDF Configuration Overview<a name="section59914284576"></a>
HCS is the source code that describes the configuration of the HDF using key-value pairs. It decouples the configuration code from driver code, thereby facilitating configuration management.
HDF Configuration Generator \(HC-GEN\) is a tool for converting a configuration file into a file that can be read by the target software.
- In a low-performance system on a chip \(SoC\), this tool can convert a configuration file into the source code of the configuration tree so that the driver can obtain the configuration by directly calling the C library code.
- In a high-performance SoC, this tool can convert an HCS configuration file into the HDF Configuration Binary \(HCB\) file, allowing the driver to obtain the configuration through the APIs provided by the HDF.
The following figure shows the typical application scenario of the HCB mode.
**Figure 1** Process of using HCS<a name="fig814111371944"></a>
![](figure/en-us_image_0000001053405727.png)
The HCS is compiled using the HC-GEN tool to generate an HCB file. The HCS Parser module in the HDF recreates a configuration tree using the HCB file. Then, the HDF driver modules obtain the configurations using the API provided by the HCS Paser.
## Configuration Syntax<a name="section533713333580"></a>
The HCS syntax is described as follows:
## Keywords<a name="section1316625413586"></a>
The keywords listed in the following table below are reserved for HCS configuration files.
**Table 1** Reserved keywords for HCS configuration files
<a name="table197619515016"></a>
<table><thead align="left"><tr id="row107621651103"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p0745257902"><a name="p0745257902"></a><a name="p0745257902"></a>Keywords</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p1974510571305"><a name="p1974510571305"></a><a name="p1974510571305"></a>Description</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p10745175720020"><a name="p10745175720020"></a><a name="p10745175720020"></a>Remarks</p>
</th>
</tr>
</thead>
<tbody><tr id="row77624515014"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p8745657307"><a name="p8745657307"></a><a name="p8745657307"></a>root</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p074525719015"><a name="p074525719015"></a><a name="p074525719015"></a>Configures the root node.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1174515575018"><a name="p1174515575018"></a><a name="p1174515575018"></a>-</p>
</td>
</tr>
<tr id="row18762175115012"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p11745175710019"><a name="p11745175710019"></a><a name="p11745175710019"></a>include</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p167458577016"><a name="p167458577016"></a><a name="p167458577016"></a>References other HCS configuration files.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p9745135718012"><a name="p9745135718012"></a><a name="p9745135718012"></a>-</p>
</td>
</tr>
<tr id="row20762251608"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p16745105712015"><a name="p16745105712015"></a><a name="p16745105712015"></a>delete</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p774585716016"><a name="p774585716016"></a><a name="p774585716016"></a>Deletes a node or an attribute.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p974514571102"><a name="p974514571102"></a><a name="p974514571102"></a>This keyword applies only to the configuration tree imported using the <strong id="b2160333103716"><a name="b2160333103716"></a><a name="b2160333103716"></a>include</strong> keyword.</p>
</td>
</tr>
<tr id="row18762751509"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p174617571907"><a name="p174617571907"></a><a name="p174617571907"></a>template</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1874610571705"><a name="p1874610571705"></a><a name="p1874610571705"></a>Defines a template node.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p774617571019"><a name="p774617571019"></a><a name="p774617571019"></a>-</p>
</td>
</tr>
<tr id="row376320511903"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p3746557501"><a name="p3746557501"></a><a name="p3746557501"></a>match_attr</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1174635712015"><a name="p1174635712015"></a><a name="p1174635712015"></a>Marks the node attribute for matching.</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1774615571508"><a name="p1774615571508"></a><a name="p1774615571508"></a>During configuration parsing, the keyword value can be used to find the corresponding node.</p>
</td>
</tr>
</tbody>
</table>
## Basic Syntax<a name="section173481622115918"></a>
The HCS configuration file consists of configurations of attributes and nodes.
**Attributes**
An attribute, as the minimum configuration unit, is an independent configuration item. Its syntax is as follows:
```
attribute_name = value;
```
- The value of **attribute\_name** is a case-sensitive string of characters starting with a letter and consisting of letters, digits, and underscores \(\_\).
- Available formats of **value** are as follows:
- A binary, octal, decimal, or hexadecimal integer. For details, see [Data Types](#section96521601302).
- A character string. The content should be enclosed in double quotation marks \(" "\).
- A node reference
- An attribute key-value pair must end with a semicolon \(;\) and belong to a node.
**Nodes**
A node is a set of attributes. Its syntax is as follows:
```
node_name {
module = "sample";
...
}
```
- The value of **node\_name** is a case-sensitive string of characters starting with a letter and consisting of letters, digits, and underscores \(\_\).
- A semicolon \(;\) is not required after the curly brace \(\}\).
- The reserved keyword **root** is used to declare the root node of a configuration table.
- The root node must contain a **module** attribute that uses a string to represent the module to which the configuration belongs.
- The **match\_attr** attribute can be added to a node. Its value is a globally unique character string. During configuration parsing, the query interface can be invoked to query the nodes with the attribute based on the attribute value.
## Data Types<a name="section96521601302"></a>
Attributes automatically use built-in data types, including integers, strings, arrays, and booleans. You do not need to explicitly specify the data type for the attribute values.
**Integer**
An integer can be binary, octal, decimal, or hexadecimal. The minimum space is automatically allocated to the integer based on the actual data length.
- Binary: prefixed with 0b, for example, 0b1010
- Octal: prefixed with 0, for example, 0664
- Decimal: either signed or unsigned, without a prefix, for example, 1024 or +1024. Negative integers can be read only via signed interfaces.
- Hexadecimal: prefixed with 0x, for example, 0xff00 and 0xFF
**String**
A string is enclosed by double quotation marks \(" "\).
**Array**
The elements in an array can be integers or strings, but cannot be a combination of both. The combination of **uint32\_t** and **uint64\_t** in an integer array will enable up-casting 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"];
```
**Boolean**
A Boolean data type has two possible values: **true** and **false**.
## Pre-processing<a name="section8164295515"></a>
**include**
The **include** keyword is used to import other HCS files. The syntax is as follows:
```
#include "foo.hcs"
#include "../bar.hcs"
```
- The file names must be enclosed by double quotation marks \(" "\). Files in different directories can be referenced using relative paths. The file included must be a valid HCS file.
- In the scenario that multiple HCS files are imported using **include**, if the same nodes exist, the latter node will override the former one, and other nodes are listed in sequence.
## Commenting<a name="section0338205819610"></a>
Comments can be formatted as follows:
- Single-line comment
```
// comment
```
- Multi-line comment
```
/*
comment
*/
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Multi-line comments cannot be nested.
## Modifying a Reference<a name="section179799204716"></a>
You can use the following syntax to modify the content of any other node:
```
node :& source_node
```
This syntax indicates that the node value is a modification of the source\_node value. Example:
```
root {
module = "sample";
foo {
foo_ :& root.bar{
attr = "foo";
}
foo1 :& foo2 {
attr = 0x2;
}
foo2 {
attr = 0x1;
}
}
bar {
attr = "bar";
}
}
```
The following configuration tree is generated:
```
root {
module = "sample";
foo {
foo2 {
attr = 0x2;
}
}
bar {
attr = "foo";
}
}
```
In the preceding example, the **foo.foo\_** node changes the value of the referenced **bar.attr** to "**foo**", and the **foo.foo1** node changes the value of the referenced **foo.foo2.attr** to **0x2**. In the generated configuration tree, **foo.foo\_** and **foo.foo1** are not displayed, but their configuration modifications are presented by their referenced nodes.
- A node of the same level can be referenced simply using the node name. A node of a different level must be referenced by the absolute path, and node names are separated using a period \(.\). **root** indicates the root node. The path format is the node path sequence starting with root. For example, **root.foo.bar** is a valid absolute path.
- If multiple modifications are made to the same attribute, only one uncertain modification can take effect, and a warning will be displayed.
## Replicating Node Configuration<a name="section382424014712"></a>
The content of a node can be replicated to another node to define the node with similar content. The syntax is as follows:
```
node : source_node
```
The preceding statement indicates that the attributes of **source\_node** are replicated to **node**. Example:
```
root {
module = "sample";
foo {
attr_0 = 0x0;
}
bar:foo {
attr_1 = 0x1;
}
}
```
The following configuration tree is generated:
```
root {
module = "sample";
foo {
attr_0 = 0x0;
}
bar {
attr_1 = 0x1;
attr_0 = 0x0;
}
}
```
In the preceding example, the **bar** node configuration includes both the **attr\_0** and **attr\_1** values. The modification to **attr\_0** in the **bar** node does not affect the **foo** node.
The path of the **foo** node is not required if the **foo** node and the **bar** node are of the same level. Otherwise, the absolute path must be used. For details, see [Modifying a Reference](#section179799204716).
## Deleting a Node or Attribute<a name="section165211112586"></a>
You can use the keyword **delete** to delete unnecessary nodes or attributes in the base configuration tree imported by the **include** keyword. In the following example, **sample1.hcs** imports the configuration of **sample2.hcs** using **include**, and deletes the **attribute2** attribute and the **foo\_2** node using the **delete** keyword.
```
// sample2.hcs
root {
attr_1 = 0x1;
attr_2 = 0x2;
foo_2 {
t = 0x1;
}
}
// sample1.hcs
#include "sample2.hcs"
root {
attr_2 = delete;
foo_2 : delete {
}
}
```
The following configuration tree is generated:
```
root {
attr_1 = 0x1;
}
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The **delete** keyword cannot be used in the same HCS file. It is recommended that you delete unnecessary attributes directly from the configuration source code.
## Referencing an Attribute<a name="section192841514490"></a>
To quickly locate the associated node during configuration parsing, you can use the node as the value of the attribute and read the attribute to find the corresponding node. The syntax is as follows:
```
attribute = &node;
```
This syntax indicates that the **attribute** value is a reference to **node**. During code parsing, you can quickly locate the node using this attribute. Example:
```
node1 {
attributes;
}
node2 {
attr_1 = &node1;
}
```
## Keyword Template<a name="section520134294"></a>
The **template** keyword is used to generate nodes with strictly consistent syntax, thereby facilitating the traverse and management of nodes of the same type.
If a node is defined using the keyword **template**, its child nodes inherit the node configuration through the double colon operator \(::\). The child nodes can modify but cannot add or 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";
template foo {
attr_1 = 0x1;
attr_2 = 0x2;
}
bar :: foo {
}
bar_1 :: foo {
attr_1 = 0x2;
}
}
```
The following configuration tree is generated:
```
root {
module = "sample";
bar {
attr_1 = 0x1;
attr_2 = 0x2;
}
bar_1 {
attr_1 = 0x2;
attr_2 = 0x2;
}
}
```
In the preceding example, the **bar** and **bar\_1** nodes inherit the **foo** node. The structures of the generated configuration tree nodes are the same as that of the **foo** node, but the attribute values are different.
## Configuration Generation<a name="section106152531919"></a>
The HC-GEN tool is used to generate configurations. It checks the HCS configuration syntax and converts HCS source files into HCB files.
## Introduction to HC-GEN<a name="section8260625101012"></a>
Parameter description:
```
Usage: hc-gen [Options] [File]
options:
-o <file> output file name, default same as input
-a hcb align with four bytes
-b output binary output, default enable
-t output config in C language source file style
-i output binary hex dump in C language source file style
-p <prefix> prefix of generated symbol name
-d decompile hcb to hcs
-V show verbose info
-v show version
-h show this help message
```
Generate a **.c** or **.h** configuration file.
```
hc-gen -o [OutputCFileName] -t [SourceHcsFileName]
```
Generate an HCB file.
```
hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName]
```
Compile an **HCB** file to an **HCS** file:
```
hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName]
```
# Driver Message Mechanism Management<a name="EN-US_TOPIC_0000001052657065"></a>
- [When to Use](#section33014541954)
- [Available APIs](#section538852311616)
- [How to Develop](#section946912121153)
## When to Use<a name="section33014541954"></a>
When user-level applications need to interact with kernel-level drivers, the driver message mechanism of the HDF can be used.
## Available APIs<a name="section538852311616"></a>
The message mechanism provides the following features:
1. User-level applications send messages to drivers.
2. User-level applications receive events sent by the drivers.
**Table 1** APIs for the driver message mechanism
<a name="table208212674114"></a>
<table><thead align="left"><tr id="row08282618416"><th class="cellrowborder" valign="top" width="46.379999999999995%" id="mcps1.2.3.1.1"><p id="p382132664112"><a name="p382132664112"></a><a name="p382132664112"></a><strong id="b142817619332"><a name="b142817619332"></a><a name="b142817619332"></a>Function</strong></p>
</th>
<th class="cellrowborder" valign="top" width="53.620000000000005%" id="mcps1.2.3.1.2"><p id="p4826264419"><a name="p4826264419"></a><a name="p4826264419"></a><strong id="b201539486743916"><a name="b201539486743916"></a><a name="b201539486743916"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row1582426174114"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p182341916144420"><a name="p182341916144420"></a><a name="p182341916144420"></a>struct HdfIoService *HdfIoServiceBind(const char *serviceName)</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p58272614113"><a name="p58272614113"></a><a name="p58272614113"></a>Obtains a specified driver service. After the service is obtained, the <strong id="b9799159433"><a name="b9799159433"></a><a name="b9799159433"></a>Dispatch</strong> function of the service is used to send messages to the driver.</p>
</td>
</tr>
<tr id="row578565084913"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p15786185024918"><a name="p15786185024918"></a><a name="p15786185024918"></a>void HdfIoServiceRecycle(struct HdfIoService *service);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p47861750154912"><a name="p47861750154912"></a><a name="p47861750154912"></a>Releases a specified driver service.</p>
</td>
</tr>
<tr id="row1382112617413"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p482182611415"><a name="p482182611415"></a><a name="p482182611415"></a>int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p18825261412"><a name="p18825261412"></a><a name="p18825261412"></a>Receives events sent by the drivers.</p>
</td>
</tr>
<tr id="row498956124019"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p6412911184019"><a name="p6412911184019"></a><a name="p6412911184019"></a>int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p1698915634018"><a name="p1698915634018"></a><a name="p1698915634018"></a>Sends events.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section946912121153"></a>
1. Set the value of the **policy** field in the driver configuration information to **2** \(SERVICE\_POLICY\_CAPACITY, see [Driver Service Management](drive-hdf-servicemanage.md)\).
```
device_sample :: Device {
policy = 2;
...
}
```
2. The **permission** field in the driver configuration information indicates the permission provided for the driver to create device nodes. The default value is **0666**. You can configure the value of this field based on the actual application scenario of the driver.
3. Implement the **Dispatch** function of the service base member **IDeviceIoService** during service implementation.
```
// Process messages delivered by user-level applications.
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("sample driver lite A dispatch");
return 0;
}
int32_t SampleDriverBind(struct HdfDeviceObject *device)
{
HDF_LOGE("test for lite os sample driver A Open!");
if (device == NULL) {
HDF_LOGE("test for lite os sample driver A Open failed!");
return -1;
}
static struct ISampleDriverService sampleDriverA = {
.ioService.Dispatch = SampleDriverDispatch,
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
device->service = (struct IDeviceIoService *)(&sampleDriverA);
return 0;
}
```
4. Define the CMD type in the message processing function.
```
#define SAMPLE_WRITE_READ 1 // Read and write operation 1
```
5. Enable the user-level application to obtain the service interface and send messages to the driver.
```
int SendMsg(const char *testMsg)
{
if (testMsg == NULL) {
HDF_LOGE("test msg is null");
return -1;
}
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return -1;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
if (!HdfSbufWriteString(data, testMsg)) {
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
}
int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("fail to send service call");
goto out;
}
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
HdfIoServiceRecycle(serv);
return ret;
}
```
6. Enable the user-level application to receive messages reported by the driver.
1. Enable the user-level application to compile the function for processing messages reported by the driver.
```
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
OsalTimespec time;
OsalGetTime(&time);
HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec);
const char *string = HdfSbufReadString(data);
if (string == NULL) {
HDF_LOGE("fail to read string in event data");
return -1;
}
HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string);
return 0;
}
```
2. Enable the user-level application to register the function for receiving messages reported by the driver.
```
int RegisterListen()
{
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
.priv ="Service0"
};
if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
HDF_LOGE("fail to register event listener");
return -1;
}
......
HdfDeviceUnregisterEventListener(serv, &listener);
HdfIoServiceRecycle(serv);
return 0;
}
```
3. Enable the driver to report events.
```
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
... // process api call here
return HdfDeviceSendEvent(deviceObject, cmdCode, data);
}
```
# HDF Development Example<a name="EN-US_TOPIC_0000001052451677"></a>
- [Adding Configurations](#section27261067111)
- [Compiling the Driver Code](#section177988005)
- [Compiling the Code for Interaction](#section6205173816412)
The following example shows how to add configurations, implement the driver code, and compile the code for interaction between the user-level applications and the driver.
## Adding Configurations<a name="section27261067111"></a>
Add the driver configurations to the HDF configuration file \(for example, **vendor/hisilicon/xxx/config/device\_info**\). Example:
```
root {
device_info {
match_attr = "hdf_manager";
template host {
hostName = "";
priority = 100;
template device {
template deviceNode {
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
sample_host :: host {
hostName = "sample_host";
sample_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 100;
preload = 1;
permission = 0664;
moduleName = "sample_driver";
serviceName = "sample_service";
}
}
}
}
}
```
## Compiling the Driver Code<a name="section177988005"></a>
A sample of driver code compiled based on the HDF is as follows:
```
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "hdf_log.h"
#include "hdf_base.h"
#include "hdf_device_desc.h"
#define HDF_LOG_TAG "sample_driver"
#define SAMPLE_WRITE_READ 123
int32_t HdfSampleDriverDispatch(
struct HdfDeviceObject *deviceObject, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("%s: received cmd %d", __func__, id);
if (id == SAMPLE_WRITE_READ) {
const char *readData = HdfSbufReadString(data);
if (readData != NULL) {
HDF_LOGE("%s: read data is: %s", __func__, readData);
}
if (!HdfSbufWriteInt32(reply, INT32_MAX)) {
HDF_LOGE("%s: reply int32 fail", __func__);
}
return HdfDeviceSendEvent(deviceObject, id, data);
}
return HDF_FAILURE;
}
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{
// Release resources here
return;
}
int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
return HDF_FAILURE;
}
static struct IDeviceIoService testService = {
.Dispatch = HdfSampleDriverDispatch,
};
deviceObject->service = &testService;
return HDF_SUCCESS;
}
int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
HDF_LOGE("%s::ptr is null!", __func__);
return HDF_FAILURE;
}
HDF_LOGE("Sample driver Init success");
return HDF_SUCCESS;
}
struct HdfDriverEntry g_sampleDriverEntry = {
.moduleVersion = 1,
.moduleName = "sample_driver",
.Bind = HdfSampleDriverBind,
.Init = HdfSampleDriverInit,
.Release = HdfSampleDriverRelease,
};
HDF_INIT(g_sampleDriverEntry);
```
## Compiling the Code for Interaction<a name="section6205173816412"></a>
A sample code for interaction between the user-level application and driver compiled based on the HDF is as follows:
```
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"
#define HDF_LOG_TAG "sample_test"
#define SAMPLE_SERVICE_NAME "sample_service"
#define SAMPLE_WRITE_READ 123
int g_replyFlag = 0;
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
const char *string = HdfSbufReadString(data);
if (string == NULL) {
HDF_LOGE("fail to read string in event data");
g_replyFlag = 1;
return HDF_FAILURE;
}
HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string);
g_replyFlag = 1;
return HDF_SUCCESS;
}
static int SendEvent(struct HdfIoService *serv, char *eventData)
{
int ret = 0;
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return 1;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
if (!HdfSbufWriteString(data, eventData)) {
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
}
ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("fail to send service call");
goto out;
}
int replyData = 0;
if (!HdfSbufReadInt32(reply, &replyData)) {
HDF_LOGE("fail to get service call reply");
ret = HDF_ERR_INVALID_OBJECT;
goto out;
}
HDF_LOGE("Get reply is: %d", replyData);
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}
int main()
{
char *sendData = "default event info";
struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);
if (serv == NULL) {
HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
return HDF_FAILURE;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
.priv ="Service0"
};
if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) {
HDF_LOGE("fail to register event listener");
return HDF_FAILURE;
}
if (SendEvent(serv, sendData)) {
HDF_LOGE("fail to send event");
return HDF_FAILURE;
}
while (g_replyFlag == 0) {
sleep(1);
}
if (HdfDeviceUnregisterEventListener(serv, &listener)) {
HDF_LOGE("fail to unregister listener");
return HDF_FAILURE;
}
HdfIoServiceRecycle(serv);
return HDF_SUCCESS;
}
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The code compilation of user-level applications depends on the dynamic libraries **hdf\_core** and **osal** provided by the HDF because user-level applications use the message sending interface of the HDF. In the GN compilation file, add the following dependency relationships:
>deps = \[
>"//drivers/adapter/lite/uhdf/manager:hdf\_core",
>"//drivers/adapter/lite/uhdf/posix:hdf\_posix\_osal",
>\]
# HDF<a name="EN-US_TOPIC_0000001157319419"></a>
- **[HDF Overview](driver-hdf-overview.md)**
- **[driverr Development](driver-hdf-development.md)**
- **[driverr Service Management](driver-hdf-servicemanage.md)**
- **[driverr Message Mechanism Management](driver-hdf-news.md)**
- **[driverr Configuration Management](driver-hdf-manage.md)**
- **[HDF Development Example](driver-hdf-sample.md)**
# Driver Message Mechanism Management<a name="EN-US_TOPIC_0000001052657065"></a>
- [When to Use](#section33014541954)
- [Available APIs](#section538852311616)
- [How to Develop](#section946912121153)
## When to Use<a name="section33014541954"></a>
When user-level applications need to interact with kernel-level drivers, the driver message mechanism of the HDF can be used.
## Available APIs<a name="section538852311616"></a>
The message mechanism provides the following features:
1. User-level applications send messages to drivers.
2. User-level applications receive events sent by the drivers.
**Table 1** APIs for the driver message mechanism
<a name="table208212674114"></a>
<table><thead align="left"><tr id="row08282618416"><th class="cellrowborder" valign="top" width="46.379999999999995%" id="mcps1.2.3.1.1"><p id="p382132664112"><a name="p382132664112"></a><a name="p382132664112"></a><strong id="b142817619332"><a name="b142817619332"></a><a name="b142817619332"></a>Function</strong></p>
</th>
<th class="cellrowborder" valign="top" width="53.620000000000005%" id="mcps1.2.3.1.2"><p id="p4826264419"><a name="p4826264419"></a><a name="p4826264419"></a><strong id="b201539486743916"><a name="b201539486743916"></a><a name="b201539486743916"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row1582426174114"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p182341916144420"><a name="p182341916144420"></a><a name="p182341916144420"></a>struct HdfIoService *HdfIoServiceBind(const char *serviceName)</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p58272614113"><a name="p58272614113"></a><a name="p58272614113"></a>Obtains a specified driver service. After the service is obtained, the <strong id="b9799159433"><a name="b9799159433"></a><a name="b9799159433"></a>Dispatch</strong> function of the service is used to send messages to the driver.</p>
</td>
</tr>
<tr id="row578565084913"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p15786185024918"><a name="p15786185024918"></a><a name="p15786185024918"></a>void HdfIoServiceRecycle(struct HdfIoService *service);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p47861750154912"><a name="p47861750154912"></a><a name="p47861750154912"></a>Releases a specified driver service.</p>
</td>
</tr>
<tr id="row1382112617413"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p482182611415"><a name="p482182611415"></a><a name="p482182611415"></a>int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p18825261412"><a name="p18825261412"></a><a name="p18825261412"></a>Receives events sent by the drivers.</p>
</td>
</tr>
<tr id="row498956124019"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p6412911184019"><a name="p6412911184019"></a><a name="p6412911184019"></a>int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p1698915634018"><a name="p1698915634018"></a><a name="p1698915634018"></a>Sends events.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section946912121153"></a>
1. Set the value of the **policy** field in the driver configuration information to **2** \(SERVICE\_POLICY\_CAPACITY, see [Driver Service Management](driver-service-management.md)\).
```
device_sample :: Device {
policy = 2;
...
}
```
2. The **permission** field in the driver configuration information indicates the permission provided for the driver to create device nodes. The default value is **0666**. You can configure the value of this field based on the actual application scenario of the driver.
3. Implement the **Dispatch** function of the service base member **IDeviceIoService** during service implementation.
```
// Process messages delivered by user-level applications.
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("sample driver lite A dispatch");
return 0;
}
int32_t SampleDriverBind(struct HdfDeviceObject *device)
{
HDF_LOGE("test for lite os sample driver A Open!");
if (device == NULL) {
HDF_LOGE("test for lite os sample driver A Open failed!");
return -1;
}
static struct ISampleDriverService sampleDriverA = {
.ioService.Dispatch = SampleDriverDispatch,
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
device->service = (struct IDeviceIoService *)(&sampleDriverA);
return 0;
}
```
4. Define the CMD type in the message processing function.
```
#define SAMPLE_WRITE_READ 1 // Read and write operation 1
```
5. Enable the user-level application to obtain the service interface and send messages to the driver.
```
int SendMsg(const char *testMsg)
{
if (testMsg == NULL) {
HDF_LOGE("test msg is null");
return -1;
}
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return -1;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
if (!HdfSbufWriteString(data, testMsg)) {
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
}
int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("fail to send service call");
goto out;
}
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
HdfIoServiceRecycle(serv);
return ret;
}
```
6. Enable the user-level application to receive messages reported by the driver.
1. Enable the user-level application to compile the function for processing messages reported by the driver.
```
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
OsalTimespec time;
OsalGetTime(&time);
HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec);
const char *string = HdfSbufReadString(data);
if (string == NULL) {
HDF_LOGE("fail to read string in event data");
return -1;
}
HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string);
return 0;
}
```
2. Enable the user-level application to register the function for receiving messages reported by the driver.
```
int RegisterListen()
{
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
.priv ="Service0"
};
if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
HDF_LOGE("fail to register event listener");
return -1;
}
......
HdfDeviceUnregisterEventListener(serv, &listener);
HdfIoServiceRecycle(serv);
return 0;
}
```
3. Enable the driver to report events.
```
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
... // process api call here
return HdfDeviceSendEvent(deviceObject, cmdCode, data);
}
```
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# Peripherals<a name="EN-US_TOPIC_0000001157319411"></a>
- **[LCD](driver-peripherals-lcd-des.md)**
- **[TOUCHSCREEN](driver-peripherals-touch-des.md)**
- **[Sensor](driver-peripherals-sensor-des.md)**
- **[WLAN](driver-peripherals-external-des.md)**
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# Driver Usage Guidelines<a name="EN-US_TOPIC_0000001111039544"></a>
- **[HDF](driver-hdf.md)**
- **[Platform Drivers](driver-platform.md)**
- **[Peripherals](driver-peripherals.md)**
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册