提交 ef788780 编写于 作者: G Gloria

replaced dev-dev (en) folder with that in master

Signed-off-by: wusongqing<wusongqing@huawei.com>
上级 abac74be
......@@ -19,7 +19,13 @@
- Mini System SoC Porting Cases
- [Mini-System Devices with Screens — Bestechnic SoC Porting Case](porting/porting-bes2600w-on-minisystem-display-demo.md)
- [Combo Solution — ASR Chip Porting Case](porting/porting-asr582x-combo-demo.md)
- [IoT Solution - Chipsea CST85 Chip Porting Case](porting/porting-cst85f01-combo-demo.md)
- [Mini System STM32F407 SoC Porting Case](porting/porting-stm32f407-on-minisystem-eth.md)
- [Combo Solution – W800 Chip Porting Case](porting/porting-w800-combo-demo.md)
- Small System SoC Porting Cases
- [Mini-System Devices – STM32MP1 SoC Porting Case](porting/porting-stm32mp15xx-on-smallsystem.md)
- Standard System SoC Porting Cases
- [Standard System Solution – Rockchip RK3568 Porting Case](porting/porting-dayu200-on_standard-demo.md)
- Subsystem Development
- Kernel
- [Kernel for the Mini System](kernel/kernel-mini-overview.md)
......@@ -47,10 +53,8 @@
- [Mini- and Small-System Devices](guide/device-wlan-led-control.md)
- [Standard-System Devices](guide/device-clock-guide.md)
- Debugging
- [Test Case Development](subsystems/subsys-testguide-test.md)
- [Test Case Development](device-test/Readme-EN.md)
- [R&D Tools](subsystems/subsys-toolchain-hdc-guide.md)
- XTS Certification
- [XTS Test Case Development](subsystems/subsys-xts-guide.md)
- Tools
- [Docker Environment](get-code/gettools-acquire.md)
- [IDE](get-code/gettools-ide.md)
......
# Device Test
- [Development Self-Test Framework User Guide](developer_test.md)
- [xDevice User Guide](xdevice.md)
- [XTS Test Case Development Guide](xts.md)
此差异已折叠。
此差异已折叠。
......@@ -4,6 +4,7 @@
- HDF
- [HDF Overview](driver-hdf-overview.md)
- [Driver Development](driver-hdf-development.md)
- [Driver Loading](driver-hdf-load.md)
- [Driver Service Management](driver-hdf-servicemanage.md)
- [Driver Message Mechanism Management](driver-hdf-message-management.md)
- [Driver Configuration Management](driver-hdf-manage.md)
......
......@@ -3,9 +3,9 @@
## Driver Model
The Hardware Driver Foundation (HDF) is designed upon a component-based driver model. This model enables refined driver management and streamlines driver development and deployment. In the HDF, the same type of device drivers are placed in a host. You can develop and deploy the drivers separately. One driver can have multiple nodes.
The Hardware Driver Foundation (HDF) is designed based on a modular driver model to enable refined driver management and streamline driver development and deployment. The HDF allows the same type of device drivers to be placed in a host. The host manages the start and loading of a group of devices. You can deploy dependent drivers to the same host, and deploy independent drivers to different hosts.
The figure below shows the HDF driver model.
The figure below shows the HDF driver model. A device refers to a physical device. A DeviceNode is a component of a device. A device has at least one DeviceNode. Each DeviceNode can publish a device service. Each DevicdNode has a unique driver to interact with the hardware.
**Figure 1** HDF driver model
......@@ -14,17 +14,15 @@ The figure below shows the HDF driver model.
## How to Develop
The HDF-based driver development process involves driver implementation, build, and configuration. The procedure is as follows:
The HDF-based driver development involves driver implementation, write of the driver compilation script, and driver configuration. The procedure is as follows:
1. Implement a driver.
Write the driver code and register the driver entry with the HDF.
- Write the driver service code.
- Write the driver service code. <br>The following is an example:
The following is an example:
```
```c
#include "hdf_device_desc.h" // Header file that defines the driver development APIs provided by the HDF.
#include "hdf_log.h" // Header file that defines the log APIs provided by the HDF.
......@@ -34,14 +32,14 @@ The HDF-based driver development process involves driver implementation, build,
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
HDF_LOGD("Sample driver bind success");
return 0;
return HDF_SUCCESS;
}
// Initialize the driver service.
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
HDF_LOGD("Sample driver Init success");
return 0;
return HDF_SUCCESS;
}
// Release the driver resources.
......@@ -51,10 +49,9 @@ The HDF-based driver development process involves driver implementation, build,
return;
}
```
- Register the driver entry with the HDF.
```
```c
// Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h).
struct HdfDriverEntry g_sampleDriverEntry = {
.moduleVersion = 1,
......@@ -64,36 +61,36 @@ The HDF-based driver development process involves driver implementation, build,
.Release = HdfSampleDriverRelease,
};
// Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
// Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls Bind() and then Init(). If Init() fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
HDF_INIT(g_sampleDriverEntry);
```
2. Build the driver.
2. Write the driver compilation script.
- LiteOS
Modify **Makefile** and **BUILD.gn** files.
Modify **makefile** and **BUILD.gn** files.
- **Makefile**:
Use the **Makefile** template provided by the HDF to compile the driver code.
Use the **makefile** template provided by the HDF to compile the driver code.
```
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # (Mandatory) Import the HDF predefined content.
```c
include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # (Mandatory) Import the HDF predefined content.
MODULE_NAME := # File to be generated.
LOCAL_INCLUDE: = # Directory of the driver header files.
LOCAL_SRCS : = # Source code files of the driver.
LOCAL_CFLAGS : = # Custom build options.
include $(HDF_DRIVER) # Import the Makefile template to complete the build.
include $(HDF_DRIVER) # Import the makefile template to complete the build.
```
Add the path of the generated file to **hdf_lite.mk** in the **drivers/adapter/khdf/liteos** directory to link the file to the kernel image. The following is an example:
Add the path of the generated file to **hdf_lite.mk** in the **drivers/hdf_core/adapter/khdf/liteos** directory to link the file to the kernel image. <br>The following is an example:
```
```c
LITEOS_BASELIB += -lxxx # Static library generated by the link.
LIB_SUBDIRS += # Directory in which Makefile is located.
LIB_SUBDIRS += # Directory in which makefile is located.
```
- **BUILD.gn**:
......@@ -101,9 +98,9 @@ The HDF-based driver development process involves driver implementation, build,
Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
```
```c
import("//build/lite/config/component/lite_component.gni")
import("//drivers/adapter/khdf/liteos/hdf.gni")
import("//drivers/hdf_core/adapter/khdf/liteos/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
module_name = "xxx"
hdf_driver(module_name) {
......@@ -119,37 +116,37 @@ The HDF-based driver development process involves driver implementation, build,
}
```
Add the **BUILD.gn** directory to **/drivers/adapter/khdf/liteos/BUILD.gn**.
Add the **BUILD.gn** directory to **/drivers/hdf_core/adapter/khdf/liteos/BUILD.gn**.
```
```c
group("liteos") {
public_deps = [ ":$module_name" ]
deps = [
"xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos.
"xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/hdf_core/adapter/khdf/liteos.
]
}
```
- Linux
To define the driver control macro, add the **Kconfig** file to the driver directory **xxx** and add the path of the **Kconfig** file to **drivers/adapter/khdf/linux/Kconfig**.
To define the driver control macro, add the **Kconfig** file to the driver directory **xxx** and add the path of the **Kconfig** file to **drivers/hdf_core/adapter/khdf/linux/Kconfig**.
```
```c
source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
```
Add the driver directory to **drivers/adapter/khdf/linux/Makefile**.
Add the driver directory to **drivers/hdf_core/adapter/khdf/linux/Makefile**.
```
```c
obj-$(CONFIG_DRIVERS_HDF) += xxx/
```
Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
```
```c
obj-y += xxx.o
```
......@@ -161,9 +158,7 @@ The HDF-based driver development process involves driver implementation, build,
- (Mandatory) Set driver device information.
The HDF loads a driver based on the driver device description defined by the HDF. Therefore, the driver device description must be added to the **device_info.hcs** file defined by the HDF.
The following is an example:
The HDF loads a driver based on the driver device description defined by the HDF. Therefore, the driver device description must be added to the **device_info.hcs** file defined by the HDF. <br>The following is an example:
```
......@@ -191,14 +186,14 @@ The HDF-based driver development process involves driver implementation, build,
sample_host :: host{
hostName = "host0"; // Host name. The host node is used as a container to hold a type of drivers.
priority = 100; // Host startup priority (0-200). A smaller value indicates a higher priority. The default value 100 is recommended. The hosts with the same priority start based on the time when the priority was configured. The host configured first starts first.
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // Linux capabilities of the user-mode process.
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // Linux capabilities of a user-mode process.
device_sample :: device { // Sample device node.
device0 :: deviceNode { // DeviceNode of the sample driver.
policy = 1; // Policy for publishing the driver service. For details, see Driver Service Management.
priority = 100; // Driver startup priority (0-200). A smaller value indicates a higher priority. The default value 100 is recommended. The drivers with the same priority start based on the time when the priority was configured. The driver configured first starts first.
preload = 0; // The driver is loaded on demand. For details, see "NOTE" at the end of this document.
permission = 0664; // Permission for the driver to create a device node.
moduleName = "sample_driver"; // Driver name. The value of this field must be the same as that of moduleName in the HdfDriverEntry structure.
preload = 0; // The value 0 means to load the driver by default during the startup of the system.
permission = 0664; // Permission for the DeviceNode created.
moduleName = "sample_driver"; // Driver name. The value must be the same as that of moduleName in the HdfDriverEntry structure.
serviceName = "sample_service"; // Name of the service published by the driver. The service name must be unique.
deviceMatchAttr = "sample_config"; // Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
}
......@@ -218,14 +213,15 @@ The HDF-based driver development process involves driver implementation, build,
>
> - The process UIDs are configured in **base/startup/init_lite/services/etc/passwd**, and the process GIDs are configured in **base/startup/init_lite/services/etc/group**. For details, see [Adding a System Service User Group]( https://gitee.com/openharmony/startup_init_lite/wikis).
>
> - If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
> - The **caps** value is in the caps = ["xxx"] format. To configure **CAP_DAC_OVERRIDE**, set this parameter to **caps = ["DAC_OVERRIDE"]**. Do not set it to **caps = ["CAP_DAC_OVERRIDE"]**.
>
> - **preload** specifies the driver loading policy. For details, see [Driver Loading](../driver/driver-hdf-load.md).
- (Optional) Set driver private information.
If the driver has private configuration, add a driver configuration file to set default driver configuration. When loading the driver, the HDF obtains and saves the driver private information in **property** of **HdfDeviceObject**, and passes the information to the driver using **Bind()** and **Init()** (see step 1).
If the driver has private configuration, add a driver configuration file to set default driver configuration. When loading the driver, the HDF obtains and saves the driver private information in **property** of **HdfDeviceObject**, and passes the information to the driver using **Bind()** and **Init()** (see step 1). <br>The following is an example of the driver configuration:
The following is an example of the driver private configuration:
```
root {
......@@ -237,40 +233,10 @@ The HDF-based driver development process involves driver implementation, build,
}
```
After the configuration, add the configuration file to the board-level configuration entry file **hdf.hcs**. (You can use DevEco to perform one-click configuration. For details, see the description about the driver development suite.)
Add the configuration file to the **hdf.hcs** file. <br>The following is an example:
The following is an example:
```
#include "device_info/device_info.hcs"
#include "sample/sample_config.hcs"
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> Drivers can be loaded on demand or in sequence.
>
> - On-demand loading
>
> ```
> typedef enum {
> DEVICE_PRELOAD_ENABLE = 0,
> DEVICE_PRELOAD_ENABLE_STEP2,
> DEVICE_PRELOAD_DISABLE,
> DEVICE_PRELOAD_INVALID
> } DevicePreload;
> ```
>
> - If **preload** in the configuration file is set to **0** (**DEVICE_PRELOAD_ENABLE**), the driver is loaded by default during the system boot process.
>
> - If **preload** is set to **1** (**DEVICE_PRELOAD_ENABLE_STEP2**), the driver is loaded after a quick start is complete. If the system does not support quick start, the value **1** has the same meaning as **DEVICE_PRELOAD_ENABLE**.
>
> - If **preload** is set to **2** (**DEVICE_PRELOAD_DISABLE**), the driver service is dynamically loaded. When a user-mode process requests the driver service, the HDF attempts to dynamically load the driver if the driver service is not available. > For more details, see [Driver Messaging Mechanism](../driver/driver-hdf-message-management.md).
>
> - Sequential loading (**preload** set to **0 (DEVICE_PRELOAD_ENABLE)**)
>
> In the configuration file, the **priority** field (ranging from 0 to 200) determines the loading sequence of a host and a driver. For drivers in different hosts, a smaller host priority value indicates a higher driver loading priority; for drivers in the same host, a smaller driver priority value indicates a higher driver loading priority.
# Driver Loading
## Overview
The HDF loads the drivers that match the configured device list.
## Driver Loading Policies
The HDF supports on-demand loading and sequential loading of drivers. The **preload** field in the configuration file (see [Driver Development](../driver/driver-hdf-development.md)) specifies the loading policy of a driver. The values are as follows:
```c
typedef enum {
DEVICE_PRELOAD_ENABLE = 0,
DEVICE_PRELOAD_ENABLE_STEP2 = 1,
DEVICE_PRELOAD_DISABLE = 2,
DEVICE_PRELOAD_INVALID
} DevicePreload;
```
### On-Demand Loading
- The value **0** (**DEVICE_PRELOAD_ENABLE**) means to load the driver by default during the system boot process.
- The value **1** (**DEVICE_PRELOAD_ENABLE_STEP2**) means to load the driver after a quick start is complete. If the system does not support quick start, the value **1** has the same meaning as **DEVICE_PRELOAD_ENABLE**.
- The value **2** (**DEVICE_PRELOAD_DISABLE**) means to load the driver dynamically. When a user-mode process requests the driver service, the HDF attempts to dynamically load the driver if the driver service is not available. For more details, see [Driver Messaging Mechanism](../driver/driver-hdf-message-management.md).
### Sequential Loading (Default)
The **priority** field (ranging from 0 to 200) in the configuration file determines the loading sequence of a host and a driver. For the drivers in different hosts, the drivers in the host with a smaller priority value are loaded first. For the drivers in the same host, the driver with a smaller priority value is loaded first.
......@@ -3,7 +3,7 @@
## HDF Configuration Overview
HDF Configuration Source (HCS) is the source code that describes the HDF configuration in key-value pairs. It decouples the configuration code from driver code, simplifying configuration management.
HDF Configuration Source (HCS) provides the source code that describes the HDF configuration in 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 an HDF configuration file into a file that can be read by the software.
......@@ -37,14 +37,14 @@ The table below describes the keywords used in the HCS syntax.
| include | References other HCS files.| - |
| delete | Deletes a node or an attribute.| Applicable only to the configuration tree referenced by **include**.|
| template | Defines a template node.| - |
| match_attr | Marks the node attribute for matching.| During configuration parsing, the attribute value can be used to locate the corresponding node.|
| match_attr | Marks the node attribute for matching.| When parsing the configuration, the driver can use the attribute value as a parameter to call an API to locate the node that has this attribute. |
### Basic Structures
The HCS has two structures: attribute and node.
**Attribute**
Attribute
An attribute is the minimum, independent configuration unit. The syntax is as follows:
......@@ -57,7 +57,7 @@ An attribute is the minimum, independent configuration unit. The syntax is as fo
- The **value** can be in any of the following formats:
- A binary, octal, decimal, or hexadecimal integer. For details, see the **Data Types** section.
- A binary, octal, decimal, or hexadecimal integer. For details, see [Data Types](#data-types).
- String quoted by double quotation marks ("").
- Node reference.
......@@ -97,7 +97,7 @@ Attributes automatically use built-in data types, including integer, string, arr
- Octal: prefixed with **0**, for example, **0664**.
- Decimal: signed or unsigned, without prefix, for example, **1024** or **+1024**. Negative integers can be read only via signed interfaces.
- Decimal: signed or unsigned, without prefix, for example, **1024** or **+1024**. Negative integers can be read only via APIs with signed numbers.
- Hexadecimal: prefixed with **0x**, for example, **0xff00** and **0xFF**.
......@@ -115,7 +115,7 @@ attr_foo = [0x01, 0x02, 0x03, 0x04];
attr_bar = ["hello", "world"];
```
**Boolean**
Boolean
Boolean data type is a form of data with only two possible values: **true** and **false**.
......@@ -324,7 +324,7 @@ node2 {
}
```
or
Or
```
......@@ -382,7 +382,7 @@ root {
In this example, the **bar** and **bar_1** nodes inherit from the **foo** node. The structure of the generated configuration tree is the same as that of the **foo** node, except that the attribute values are different.
## **Configuration Generation**
## Configuration Generation
The HC-GEN tool checks the HCS configuration syntax and converts HCS source files into HCB files.
......
......@@ -10,23 +10,23 @@ The HDF messaging mechanism implements the interaction between the user-mode app
The messaging mechanism allows:
1. User-mode applications to send messages to drivers.
1. A user-mode application to send a message to a driver.
2. User-mode applications to receive events from drivers.
2. A user-mode application to receive events reported by a driver.
**Table 1** APIs for the driver messaging mechanism
| API| Description|
| -------- | -------- |
| struct&nbsp;HdfIoService&nbsp;\*HdfIoServiceBind(const&nbsp;char&nbsp;\*serviceName); | Obtains a driver service. The **Dispatch()** method in the driver service obtained sends messages to the driver.|
| void&nbsp;HdfIoServiceRecycle(struct&nbsp;HdfIoService&nbsp;\*service); | Releases a driver service.|
| int&nbsp;HdfDeviceRegisterEventListener(struct&nbsp;HdfIoService&nbsp;\*target,&nbsp;struct&nbsp;HdfDevEventlistener&nbsp;\*listener); | Registers the method for receiving events reported by the driver.|
| int&nbsp;HdfDeviceSendEvent(struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject,&nbsp;uint32_t&nbsp;id,&nbsp;struct&nbsp;HdfSBuf&nbsp;\*data); | Sends events. |
| struct HdfIoService \*HdfIoServiceBind(const char \*serviceName); | Obtains a driver service. After obtaining the driver service, the user-mode application uses **Dispatch()** in the driver service obtained to send messages to the driver.|
| void HdfIoServiceRecycle(struct HdfIoService \*service); | Releases a driver service.|
| int HdfDeviceRegisterEventListener(struct HdfIoService \*target, struct HdfDevEventlistener \*listener); | Registers the method for receiving events reported by the driver.|
| int HdfDeviceSendEvent(struct HdfDeviceObject \*deviceObject, uint32_t id, struct HdfSBuf \*data); | Sends events. |
## How to Develop
1. In the driver configuration, set **policy** to **2**. For more details, see [policy](../driver/driver-hdf-servicemanage.md).
1. In the driver configuration file, set **policy** to **2**. For more details, see [Driver Service Management](../driver/driver-hdf-servicemanage.md).
```
device_sample :: Device {
......@@ -35,23 +35,23 @@ The messaging mechanism allows:
}
```
2. Set the driver permission. By default, the **permission** field is set to **0666**, which allows the driver to create device nodes. You can set this field based on service requirements.
2. Set permissions for the device node of the driver. By default, the **permission** field is set to **0666**. You can set it based on service requirements.
3. Implement the **Dispatch()** method of **IDeviceIoService**.
```
// Dispatch messages sent from the user-mode application.
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
```c
// Dispatch() is used to process messages sent from the user-mode application.
int32_t SampleDriverDispatch(struct HdfDeviceIoClient *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("sample driver lite A dispatch");
return 0;
HDF_LOGI("sample driver lite A dispatch");
return HDF_SUCCESS;
}
int32_t SampleDriverBind(struct HdfDeviceObject *device)
{
HDF_LOGE("test for lite os sample driver A Open!");
HDF_LOGI("test for lite os sample driver A Open!");
if (device == NULL) {
HDF_LOGE("test for lite os sample driver A Open failed!");
return -1;
return HDF_FAILURE;
}
static struct ISampleDriverService sampleDriverA = {
.ioService.Dispatch = SampleDriverDispatch,
......@@ -59,36 +59,36 @@ The messaging mechanism allows:
.ServiceB = SampleDriverServiceB,
};
device->service = (struct IDeviceIoService *)(&sampleDriverA);
return 0;
return HDF_SUCCESS;
}
```
4. Define the cmd type in the message processing function.
```
```c
#define SAMPLE_WRITE_READ 1 // Read and write operation 1
```
5. Bind the driver service and the user-mode application to enable messages to be sent to the driver.
5. Enable the user-mode application to obtain a service and send a message to the driver.
```
```c
int SendMsg(const char *testMsg)
{
if (testMsg == NULL) {
HDF_LOGE("test msg is null");
return -1;
return HDF_FAILURE;
}
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
return HDF_FAILURE;
}
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
struct HdfSBuf *data = HdfSbufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return -1;
return HDF_FAILURE;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
......@@ -105,41 +105,41 @@ The messaging mechanism allows:
goto out;
}
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
HdfSbufRecycle(data);
HdfSbbufRecycle(reply);
HdfIoServiceRecycle(serv);
return ret;
}
```
6. Enable the user-mode application to receive messages from the driver.
1. Enable the driver to report events to the user-mode application.
1. Implement the method for the user-mode application to process the events reported by the driver.
```
```c
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);
HDF_LOGI("%{public}s received event at %{public}llu.%{public}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;
return HDF_FAILURE;
}
HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string);
return 0;
HDF_LOGI("%{public}s: dev event received: %{public}d %{public}s", (char *)priv, id, string);
return HDF_SUCCESS;
}
```
2. Register the method for receiving the messages from the driver.
2. Register the method for the user-mode application to receive messages from the driver.
```
```c
int RegisterListen()
{
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
return HDF_FAILURE;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
......@@ -147,20 +147,20 @@ The messaging mechanism allows:
};
if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
HDF_LOGE("fail to register event listener");
return -1;
return HDF_FAILURE;
}
......
HdfDeviceUnregisterEventListener(serv, &listener);
HdfIoServiceRecycle(serv);
return 0;
return HDF_SUCCESS;
}
```
3. Enable the driver to report events.
```
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
```c
int32_t SampleDriverDispatch(HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
... // Process the API call.
return HdfDeviceSendEvent(deviceObject, cmdCode, data);
// Process the API call.
return HdfDeviceSendEvent(client->device, cmdCode, data);
}
```
......@@ -3,7 +3,7 @@
## Introduction
The Hardware Driver Foundation (HDF) provides driver framework capabilities including driver loading, driver service management, and driver messaging mechanism. It strives to build a unified driver architecture platform to provide a more precise and efficient development environment, where you can perform one-time development for multi-device deployment.
The Hardware Driver Foundation (HDF) provides driver framework capabilities, such as driver loading, driver service management, driver messaging mechanism, and configuration management, for driver developers. It strives to provide a more precise and efficient driver development environment, where you can perform one-time development for multi-device deployment.
## Driver Loading
......@@ -12,18 +12,23 @@ The HDF supports the following loading modes:
- On-demand loading
The driver is loaded by default during the operating system (OS) boot process or dynamically loaded after OS is started.
The HDF allows drivers to be loaded by default during the operating system (OS) boot process or dynamically loaded after the OS is started.
- Sequential loading
The driver is loaded based on its priority during the OS boot process.
The HDF allows drivers to be loaded based on their priorities during the OS boot process.
## Driver Service Management
The HDF allows centralized management of driver services. You can obtain a driver service by using the API provided by the HDF.
The HDF supports centralized management of driver services. You can obtain a driver service by using the API provided by the HDF.
## Driver messaging mechanism
## Driver Messaging Mechanism
The HDF provides a unified driver messaging mechanism, which allows messages to be exchanged between user-mode applications and kernel-mode drivers.
## Configuration Management
HDF Configuration Source (HCS) provides the source code that describes the HDF configuration in key-value pairs. It decouples the configuration code from driver code, simplifying configuration management.
......@@ -51,7 +51,7 @@ root {
Write the driver code based on the HDF. For more details, see [Driver Development](../driver/driver-hdf-development.md).
```
```c
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
......@@ -59,34 +59,34 @@ Write the driver code based on the HDF. For more details, see [Driver Developmen
#include "hdf_base.h"
#include "hdf_device_desc.h"
#define HDF_LOG_TAG "sample_driver"
#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)
static int32_t HdfSampleDriverDispatch(
struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("%s: received cmd %d", __func__, id);
HDF_LOGI("%{public}s: received cmd %{public}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);
HDF_LOGE("%{public}s: read data is: %{public}s", __func__, readData);
}
if (!HdfSbufWriteInt32(reply, INT32_MAX)) {
HDF_LOGE("%s: reply int32 fail", __func__);
HDF_LOGE("%{public}s: reply int32 fail", __func__);
}
return HdfDeviceSendEvent(deviceObject, id, data);
return HdfDeviceSendEvent(client->device, id, data);
}
return HDF_FAILURE;
}
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
static void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{
// Release resources.
return;
}
int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
static int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
return HDF_FAILURE;
......@@ -98,17 +98,17 @@ int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
return HDF_SUCCESS;
}
int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
static int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
HDF_LOGE("%s::ptr is null!", __func__);
HDF_LOGE("%{public}s::ptr is null!", __func__);
return HDF_FAILURE;
}
HDF_LOGE("Sample driver Init success");
HDF_LOGI("Sample driver Init success");
return HDF_SUCCESS;
}
struct HdfDriverEntry g_sampleDriverEntry = {
static struct HdfDriverEntry g_sampleDriverEntry = {
.moduleVersion = 1,
.moduleName = "sample_driver",
.Bind = HdfSampleDriverBind,
......@@ -122,10 +122,10 @@ HDF_INIT(g_sampleDriverEntry);
## Implementing Interaction Between the Application and the Driver
Write the code for interaction between the user-mode application and the driver. Place the code in the **drivers/adapter/uhdf** directory for compilation. For details about **build.gn**, see **drivers/framework/sample/platform/uart/dev/build.gn**.
Write the code for interaction between the user-mode application and the driver. Place the code in the **drivers/hdf_core/adapter/uhdf** directory for compilation. For details about **BUILD.gn**, see **drivers/hdf_core/framework/sample/platform/uart/dev/BUILD.gn**.
```
```c
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
......@@ -134,7 +134,7 @@ Write the code for interaction between the user-mode application and the driver.
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"
#define HDF_LOG_TAG "sample_test"
#define HDF_LOG_TAG sample_test
#define SAMPLE_SERVICE_NAME "sample_service"
#define SAMPLE_WRITE_READ 123
......@@ -149,7 +149,7 @@ static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
g_replyFlag = 1;
return HDF_FAILURE;
}
HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string);
HDF_LOGI("%{public}s: dev event received: %{public}u %{public}s", (char *)priv, id, string);
g_replyFlag = 1;
return HDF_SUCCESS;
}
......@@ -157,13 +157,13 @@ static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
static int SendEvent(struct HdfIoService *serv, char *eventData)
{
int ret = 0;
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
struct HdfSBuf *data = HdfSbufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return 1;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
......@@ -188,10 +188,10 @@ static int SendEvent(struct HdfIoService *serv, char *eventData)
ret = HDF_ERR_INVALID_OBJECT;
goto out;
}
HDF_LOGE("Get reply is: %d", replyData);
HDF_LOGI("Get reply is: %{public}d", replyData);
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
HdfSbufRecycle(data);
HdfSbufRecycle(reply);
return ret;
}
......@@ -237,8 +237,8 @@ int main()
>
> deps = [
>
> "//drivers/adapter/uhdf/manager:hdf_core",
> "//drivers/hdf_core/adapter/uhdf/manager:hdf_core",
>
> "//drivers/adapter/uhdf/posix:hdf_posix_osal",
> "//drivers/hdf_core/adapter/uhdf/posix:hdf_posix_osal",
>
> ]
......@@ -8,7 +8,7 @@ The HDF uses the **policy** field in the configuration file to define policies f
```
```c
typedef enum {
/* The driver does not provide services. */
SERVICE_POLICY_NONE = 0,
......@@ -28,7 +28,7 @@ typedef enum {
## When to Use
The driver service management capability can be used if the driver provides capabilities using APIs.
You can use the driver service management capability of the HDF when the driver needs to provide capabilities via APIs.
## Available APIs
......@@ -48,9 +48,9 @@ The table below describes the APIs for driver service management.
The development procedure is as follows:
1. Define the services to be published by the driver.
1. Define the service to be published by the driver.
```
```c
// Define the driver service structure.
struct ISampleDriverService {
struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type.
......@@ -62,70 +62,69 @@ The development procedure is as follows:
int32_t SampleDriverServiceA(void)
{
// You need to implement the service logic.
return 0;
return HDF_SUCCESS;
}
int32_t SampleDriverServiceB(uint32_t inputCode)
{
// You need to implement the service logic.
return 0;
return HDF_SUCCESS;
}
```
2. Bind the driver service to the HDF and implement the **Bind()** function in the **HdfDriverEntry** structure.
2. Bind the driver service.
```
Implement the **Bind** pointer function, for example, **SampleDriverBind**, in **HdfDriverEntry** to bind the driver service to the HDF.
```c
int32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
{
// deviceObject is a pointer to the device object created by the HDF for each driver. The device object holds private device data and service APIs.
if (deviceObject == NULL) {
HDF_LOGE("Sample device object is null!");
return -1;
return HDF_FAILURE;
}
static struct ISampleDriverService sampleDriverA = {
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
deviceObject->service = &sampleDriverA.ioService;
return 0;
return HDF_SUCCESS;
}
```
3. Obtain the driver service.
The driver service can be obtained by using the API or subscription mechanism provided by the HDF.
The driver service can be obtained by using either of the following methods:
- Using the API
- Using the API provided by the HDF
Use the API provided by the HDF to obtain the driver service if the driver has been loaded.
If the service requester clearly knows the time when the driver is loaded, use the API provided by the HDF to obtain the driver service. The following is an example:
```
​```
```c
const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
if (sampleService == NULL) {
return -1;
return HDF_FAILURE;
}
sampleService->ServiceA();
sampleService->ServiceB(5);
​```
```
- Using the subscription mechanism
If the kernel mode is unaware of the time for loading drivers on the same host, use the subscription mechanism provided by the HDF to subscribe to the drivers. After the drivers are loaded, the HDF publishes the driver services to the subscriber.
If the service requester is unaware of the time when the driver (in the same host) is loaded, use the subscription mechanism provided by the HDF to subscribe to the service. After the driver is loaded, the HDF publishes the driver service to the subscriber. The implementation is as follows:
The implementation is as follows:
```
// Callback invoked to return the driver services after the subscribed driver is loaded.
```c
// Callback invoked to return the driver service after the subscribed driver is loaded.
// object is the pointer to the private data of the subscriber, and service is the pointer to the subscribed service object.
int32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
{
const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)service;
if (sampleService == NULL) {
return -1;
return HDF_FAILURE;
}
sampleService->ServiceA();
sampleService->ServiceB(5);
......@@ -135,18 +134,15 @@ The development procedure is as follows:
{
if (deviceObject == NULL) {
HDF_LOGE("Test driver init failed, deviceObject is null!");
return -1;
return HDF_FAILURE;
}
struct SubscriberCallback callBack;
callBack.deviceObject = deviceObject;
callBack.OnServiceConnected = TestDriverSubCallBack;
int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
if (ret != 0) {
if (ret != HDF_SUCCESS) {
HDF_LOGE("Test driver subscribe sample driver failed!");
}
return ret;
}
```
......@@ -84,7 +84,7 @@ The codec module implements hardware encoding and decoding of video data. It con
For more information, see [codec](https://gitee.com/openharmony/drivers_peripheral/tree/master/codec).
### Development Procedure
### How to Develop
The codec HDI driver development procedure is as follows:
#### Registering and Initializing the Driver
......
......@@ -5,22 +5,22 @@
### WLAN
The Wireless Local Area Network (WLAN) Driver module in OpenHarmony is developed based on the Hardware Driver Foundation (HDF). It provides cross-OS porting, self-adaptation to component differences, and module assembly and building.
The Wireless Local Area Network (WLAN) driver module is developed based on OpenHarmony Hardware Driver Foundation (HDF). It supports modular assembly and building, automatic adaptation to device differences, and cross-OS porting.
### Working Principles
You can adapt your driver code based on the unified interfaces provided by the WLAN module. The WLAN module provides:
You can modify your driver code based on the unified APIs provided by the WLAN module. The WLAN module provides:
- A unified underlying interface to implement capabilities, such as setting up or closing a WLAN hotspot, scanning hotspots, and connecting to or disconnecting from a hotspot.
- A unified interface to the Hardware Device Interface (HDI) layer to implement capabilities, such as setting or obtaining the device Media Access Control (MAC) address and setting the transmit power.
- APIs for the underlying layer to implement capabilities, such as opening or closing a WLAN hotspot, scanning hotspots, and connecting to or disconnecting from a hotspot.
- APIs for the Hardware Device Interface (HDI) layer to implement capabilities, such as setting or obtaining the device Media Access Control (MAC) address and setting the transmit power.
The figure below shows the WLAN architecture. The WLAN Driver module implements startup loading, parses configuration files, and provides bus abstraction APIs. The WLAN Chip Driver module provides the MAC Sublayer Management Entity (MLME).
The following figure shows the WLAN architecture. The WLAN driver module implements startup loading, parses configuration files, and provides bus abstraction APIs. The WLAN chip driver module provides the MAC Sublayer Management Entity (MLME).
**Figure 1** WLAN architecture
![image](figures/WLAN_architecture.png "WLAN architecture")
The figure below shows the WLAN driver architecture.
The following figure shows the WLAN driver architecture.
**Figure 2** WLAN driver architecture
......@@ -32,11 +32,11 @@ The WLAN driver consists of the following modules:
2. WLAN Configuration Core: parses WLAN configuration files.
3. Access point (AP): provides a WLAN access interface for devices.
3. Access point (AP): allows devices to connect to the WLAN.
4. Station (STA): a terminal that accesses the WLAN system.
4. Station (STA): a device that has access to the WLAN system and allows transmission and reception of data.
5. mac80211: defines MAC-layer interfaces for underlying drivers.
5. mac80211: defines MAC-layer APIs for underlying drivers.
6. Bus: provides a unified bus abstract interface for the upper layer. It shields the differences between different kernels by calling the Secure Digital Input Output (SDIO) interfaces provided by the platform layer and encapsulating the adapted USB and PCIe interfaces. It also encapsulates different types of bus operations in a unified manner to shield differences between different chipsets. The complete bus driving capabilities provided by the bus module help simplify and streamline the development of different chip vendors.
......@@ -58,13 +58,13 @@ The relationships between the main modules are as follows:
4. The protocol stack works with the NetDevice, NetBuf, and FlowCtl modules to exchange data flows.
## Development Guidelines
## How to Develop
### Available APIs
The WLAN module provides the following types of APIs:
1. Hardware Device Interface (HDI) and Hardware Abstraction Layer (HAL) APIs for upper-layer services
1. HDI and Hardware Abstraction Layer (HAL) APIs for upper-layer services
2. APIs for vendors
......@@ -75,7 +75,7 @@ The WLAN module provides the following types of APIs:
![image](figures/WLAN_driver_APIs.png "WLAN Driver APIs")
- The WLAN module provides HAL APIs for upper-layer services (applicable to small and mini systems). **Table 2** and **Table 3** describe some APIs.
- The WLAN module provides HAL APIs for upper-layer services (applicable to small and mini systems). **Table 1** and **Table 2** describe some APIs.
**Table 1** wifi_hal.h
......@@ -95,7 +95,7 @@ The WLAN module provides the following types of APIs:
| int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Obtains the device MAC address.|
| int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t)| Sets the transmit power.|
- The WLAN Driver module also provides APIs that you need to fill in the implementation. **Table 4** describes some APIs.
- The WLAN Driver module also provides APIs that you need to fill in the implementation. **Table 3** describes some APIs.
**Table 3** net_device.h
......@@ -110,7 +110,7 @@ The WLAN module provides the following types of APIs:
- The WLAN Driver module provides APIs that you can directly use to create or release a **WifiModule**, connect to or disconnect from a WLAN hotspot, request or release a **NetBuf**, and convert between the **pbuf** structure of Lightweight IP (lwIP) and a **NetBuf**.
Tables 5 to 7 describe the APIs.
The following tables describe the APIs.
**Table 4** wifi_module.h
......@@ -119,7 +119,7 @@ The WLAN module provides the following types of APIs:
| struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config)| Creates a **WifiModule**.|
| void WifiModuleDelete(struct WifiModule \*module)| Deletes a **WifiModule** and releases its data.|
| int32_t DelFeature(struct WifiModule \*module, uint16_t featureType)| Deletes a feature from a **WifiModule**.|
| int32_t AddFeature(struct WifiModule \*module, uint16_t featureType, struct WifiFeature \*featureData)| Adds a feature to a **WifiModule**.|
| int32_t AddFeature(struct WifiModule \*module, uint16_t featureType,<br> struct WifiFeature \*featureData)| Adds a feature to a **WifiModule**.|
**Table 5** wifi_mac80211_ops.h
......@@ -136,11 +136,11 @@ The WLAN module provides the following types of APIs:
| -------- | -------- |
| static inline void NetBufQueueInit(struct NetBufQueue \*q)| Initializes a **NetBuf** queue.|
| struct NetBuf \*NetBufAlloc(uint32_t size)| Allocates a **NetBuf**.|
| void NetBufFree(struct NetBuf \*nb) | Releases a **NetBuf**.|
| void NetBufFree(struct NetBuf \*nb)| Releases a **NetBuf**.|
| struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf)| Converts the **pbuf** structure of lwIP to a **NetBuf**.|
| struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb)| Converts a **NetBuf** to the **pbuf** structure of lwIP.|
### How to Develop
### Development Procedure
#### WLAN Framework Adaptation
The WLAN driver framework developed based on the HDF and Platform framework provides a unified driver model regardless of the OS and system on a chip (SoC). When developing your WLAN driver, you need to configure data based on the WLAN driver framework.
......@@ -546,11 +546,7 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
}
```
4. Invoke the event reporting APIs.
The WLAN framework provides the event reporting APIs. For details, see **hdf_wifi_event.c**.
For example, call **HdfWiFiEventNewSta AP** to report information about the newly associated STA.
4. Invoke the event reporting APIs. <br>The WLAN framework provides the event reporting APIs. For details, see hdf_wifi_event.c. <br>For example, call **HdfWiFiEventNewSta AP** to report information about the newly associated STA.
```c
hi_u32 oal_cfg80211_new_sta(oal_net_device_stru *net_device, const hi_u8 *mac_addr, hi_u8 addr_len,
......@@ -571,8 +567,6 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
return HI_SUCCESS;
}
```
**Verification**
Develop test cases in the WLAN module unit test to verify the basic features of the WLAN module. The following uses Hi3516D V300 standard system as an example.
......@@ -650,7 +644,7 @@ Develop test cases in the WLAN module unit test to verify the basic features of
exit 0
```
- Create a **udhcpd.conf** file (used to start the **udhcpd**) and copy the following content to the file. In the following, **opt dns** *x.x.x.x* *x.x.x.x* indicates two DNS servers configured. You can configure DNS servers as required.
- Create a **udhcpd.conf** file (used to start the **udhcpd**) and copy the following content to the file. <br>In the following, **opt dns** *x.x.x.x* *x.x.x.x* indicates two DNS servers configured. You can configure DNS servers as required.
```text
start 192.168.12.2
......@@ -704,9 +698,7 @@ Develop test cases in the WLAN module unit test to verify the basic features of
busybox udhcpd /vendor/etc/udhcpd.conf
```
4. On the mobile phone, select the network named **test** in the available Wi-Fi list and enter the password.
The network name and password are configured in the **hostapd.conf** file. You can see that network name in the connected Wi-Fi list if the connection is successful.
4. On the mobile phone, select the network named **test** in the available Wi-Fi list and enter the password. <br>The network name and password are configured in the **hostapd.conf** file. You can see that network name in the connected Wi-Fi list if the connection is successful.
5. Ping the test terminal from the development board.
......@@ -714,15 +706,11 @@ Develop test cases in the WLAN module unit test to verify the basic features of
busybox ping xxx.xxx.xxx.xxx
```
In the command, xxx.xxx.xxx.xxx indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
In the command, *xxx.xxx.xxx.xxx* indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
- Verify basic STA features.
1. Start the STA on the development board, and enable the hotspot on the test terminal.
The hotspot name and password are configured in the **hostapd.conf** file. The hotspot name is **test**, and the password is **12345678**.
1. Start the STA on the development board, and enable the hotspot on the test terminal. <br>The hotspot name and password are configured in the **hostapd.conf** file. The hotspot name is **test**, and the password is **12345678**.
2. Run the following command in the **cmd** window:
......@@ -731,8 +719,6 @@ Develop test cases in the WLAN module unit test to verify the basic features of
wpa_supplicant -i wlan0 -d -c wpa_supplicant.conf
```
3. Run the following commands in another **cmd** window:
```shell
......@@ -741,7 +727,6 @@ Develop test cases in the WLAN module unit test to verify the basic features of
mount -o rw,remount /vendor
busybox udhcpc -i wlan0 -s system/lib/dhcpc.sh
```
The IP addresses of the board and test terminal are displayed if the command is successful.
4. Ping the test terminal from the development board.
......@@ -750,8 +735,7 @@ Develop test cases in the WLAN module unit test to verify the basic features of
busybox ping xxx.xxx.xxx.xxx
```
In the command, *xxx.xxx.xxx.xxx* indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
In the command, xxx.xxx.xxx.xxx indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
#### **API Invocation**
The WLAN driver module provides two types of capability interfaces for the upper layer: HDI interface and HAL interface.
......@@ -963,19 +947,17 @@ The WLAN driver module provides two types of capability interfaces for the upper
- Code paths:
- Adaptation of WLAN FlowCtl component on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi**
- Adaptation of HDF network model on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network**
- Adaptation of WLAN FlowCtl component on Linux, build of the HDF WLAN model, and build of the vendor's WLAN driver: **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi**
- Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi**
- External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi**
- HDF network model APIs: **//drivers/hdf_core/framework/include/net**
- WLAN HDI server implementation: **//drivers/peripheral/wlan**
Adaptation of WLAN FlowCtl component on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi**
Adaptation of HDF network model on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network**
Adaptation of WLAN FlowCtl component on Linux, build of the HDF WLAN model, and build of the vendor's WLAN driver: **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi**
Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi**
External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi**
HDF network model APIs: **//drivers/hdf_core/framework/include/net**
WLAN HDI server implementation: **//drivers/peripheral/wlan**
# LCD
## Overview
### Function
The Liquid Crystal Display (LCD) driver performs operations such as powering on the LCD and initializing the internal registers of the driver integrated circuits (ICs).
The display driver model developed based on the Hardware Driver Foundation [(HDF)](../driver/driver-hdf-overview.md) provides a basic framework for LCD driver development, improves driver development efficiency, and facilitates porting of the driver across OSs and chip platforms. The figure below shows the HDF-based display driver model.
The display driver model based on the [Hardware Driver Foundation (HDF)](../driver/driver-hdf-overview.md) provides the following functions:
- Provides a basic framework for LCD driver development to improve development efficiency.
- Facilitates driver porting across OSs and chip platforms.
The following figure shows the HDF-based display driver model.
**Figure 1** HDF-based display driver model
![image](figures/architecture-of-the-display-driver-model.png "Display Driver Model")
The display driver model consists of the display common driver layer, SoC adapter layer, and LCD panel driver layer. The HDF-based display driver model shields the differences between kernel forms through platform and OSAL APIs so the LCD driver can be easily ported between different OSs and chip platforms. The display driver model connects to the display common Hardware Abstraction Layer (HAL), supports the implementation of the Hardware Device Interface (HDI), and provides various driver capability interfaces for graphics services through the Display-HDI.
The display driver model consists of the display common driver layer, SoC adapter layer, and LCD panel driver layer. The HDF-based display driver model shields the differences between kernel forms through platform and OSAL APIs so that the LCD driver can be easily ported across OSs and chip platforms. The display driver model connects to the display common Hardware Abstraction Layer (HAL), supports the implementation of the Hardware Device Interface (HDI), and provides various driver capability interfaces for graphics services through the Display-HDI.
- Display common driver layer: connects to the display common HAL through the IOService data channel provided by the HDF to receive and process various upper-layer calls in a centralized manner.
......@@ -23,8 +29,7 @@ The display driver model consists of the display common driver layer, SoC adapte
The display driver model leverages the capabilities and APIs provided by the platform to simplify the display driver development and improve the efficiency.
## Available APIs
### Basic Concepts
The LCD interfaces include the Mobile Industry Processor Interface (MIPI) Display Serial Interface (DSI), Transistor-Transistor Logic (TTL) interface, and Low Voltage Differential Signaling (LVDS) interface. The MIPI DSI and TTL interfaces are commonly used. Here is a brief introduction to them.
......@@ -42,14 +47,31 @@ The LCD interfaces include the Mobile Industry Processor Interface (MIPI) Displa
![](figures/ttl-interface.png "ttl-interface")
TTL level signals are generated by TTL devices, which are a major type of digital integrated circuits. TTL devices are manufactured using the bipolar process and feature high speed, low power consumption, and diversified types.
TTL level signals are generated by TTL devices, which are a major type of digital integrated circuits. TTL devices are manufactured using the bipolar process and feature high speed, low power consumption, and diversified types.
The TTL interface is used to transmit data in parallel mode under control signals. It transmits data signals, clock signals, and control signals (such as line synchronization signals, frame synchronization signals, and data validity signals). For the LCD with the TTL, additional peripheral interfaces, such as the Serial Peripheral Interface (SPI) and Inter-Integrated Circuit (I2C), are required for the read and write of the internal registers.
### Constraints
In addition to the IC model, you must consider the LCD peripheral circuit design, LCD interface unit of the baseband chip, backlight IC control, and upper-layer software programs. All these factors affect the development of the LCD driver.
## Development Guidelines
### When to Use
## How to Develop
Before applying your device with OpenHarmony system, you need to perform LCD driver adaption. The HDF-based display driver model provides a unified driver model for LCD adaptation regardless of the OS (LiteOS or Linux OS) and chip platform (Hi35xx, Hi38xx, or V3S).
The HDF-based display driver model provides a unified driver model for LCDs regardless of the OS (LiteOS or Linux OS) and chip platform (Hi35xx, Hi38xx, or V3S). The development procedure is as follows:
### Available APIs
Table 1 APIs required for LCD driver adaptation
| API | Description |
| :------------------------------------------------------ | ------------------- |
| display :: host | Sets device information. |
| static int32_t LcdResetOn(void) | Sets the status of the reset pin.|
| int32_t SampleEntryInit(struct HdfDeviceObject *object) | Initializes the entry function of the device driver. |
### How to Develop
1. Add the device configuration related to the LCD driver.
......@@ -58,23 +80,26 @@ The HDF-based display driver model provides a unified driver model for LCDs rega
3. Add the LCD panel driver and register the panel driver functions in the driver entry function **Init**. The functions provide capabilities for:
- Powering on/off the LCD device
Based on the LCD hardware connection, use the GPIO APIs provided by the platform to perform operations on the LCD pins, such as the reset pin and IOVCC pin. For details about the power-on sequence, see the SPEC provided by the LCD supplier.
- Sending the initialization sequence
Based on the LCD hardware interfaces, use the I2C, SPI, and MIPI interfaces provided by the platform to download the LCD initialization sequence. For details, see the SPEC provided by the LCD supplier.
4. Implement other HDF APIs as required, for example, **Release()**.
Based on the LCD hardware interfaces, use the I2C, SPI, and MIPI interfaces provided by the platform to download the LCD initialization sequence. For details, see the SPEC provided by the LCD supplier.
5. Use the HDF to create other device nodes for implementing service logic or debugging as required.
4. (Optional) Implement other HDF APIs, such as **Release()**, as required.
5. (Optional) Create other device nodes for implementing service logic or debugging based on the HDF as required.
## Development Example
### Example
Add the device configuration.
The following uses the Hi35xx series chips as an example to describe how to perform LCD driver adaptation.
1. Add device information in the **vendor/bearpi/bearpi_hm_micro/hdf_config/device_info/device_info.hcs** file.
```
/* Configuration of the devices related to the display driver */
display :: host {
```c++
/* Configuration of the devices related to the display driver */
display :: host {
hostName = "display_host";
/* Configuration of the HDF display driver */
device_hdf_disp :: device {
......@@ -109,15 +134,15 @@ display :: host {
moduleName = "LCD_SampleXX";
}
}
}
```
Adapt the driver to the chip at the SoC adapter layer. The following example shows how to adapt the MIPI device to the Hi35xx series chips at the SoC adapter layer:
}
```
2. Configure the chip platform driver information in the **drivers/hdf_core/framework/model/display/driver/adapter_soc/hi35xx_disp.c file**.
```
static int32_t MipiDsiInit(struct PanelInfo *info)
{
```c++
/* Configuration of the display driver to adapt to the MIPI and chip platform */
static int32_t MipiDsiInit(struct PanelInfo *info)
{
int32_t ret;
struct DevHandle *mipiHandle = NULL;
struct MipiCfg cfg;
......@@ -152,34 +177,37 @@ static int32_t MipiDsiInit(struct PanelInfo *info)
HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__,
cfg.pixelClk, cfg.phyDataRate);
return ret;
}
```
Develop an LCD driver. The sample code is as follows:
```
#define RESET_GPIO 5
#define MIPI_DSI0 0
#define BLK_PWM1 1
#define PWM_MAX_PERIOD 100000
/* Set the backlight. */
#define MIN_LEVEL 0
#define MAX_LEVEL 255
#define DEFAULT_LEVEL 100
#define WIDTH 480
#define HEIGHT 960
#define HORIZONTAL_BACK_PORCH 20
#define HORIZONTAL_FRONT_PORCH 20
#define HORIZONTAL_SYNC_WIDTH 10
#define VERTICAL_BACK_PORCH 14
#define VERTICAL_FRONT_PORCH 16
#define VERTICAL_SYNC_WIDTH 2
#define FRAME_RATE 60
/* PanelInfo structure */
struct PanelInfo {
}
```
3. Add a device in **drivers/hdf_core/framework/model/display/driver/panel/mipi_icn9700.c**.
- Define driver-related interface information.
```c++
#define RESET_GPIO 5
#define MIPI_DSI0 0
#define BLK_PWM1 1
#define PWM_MAX_PERIOD 100000
/* Set the backlight. */
#define MIN_LEVEL 0
#define MAX_LEVEL 255
#define DEFAULT_LEVEL 100
#define WIDTH 480
#define HEIGHT 960
#define HORIZONTAL_BACK_PORCH 20
#define HORIZONTAL_FRONT_PORCH 20
#define HORIZONTAL_SYNC_WIDTH 10
#define VERTICAL_BACK_PORCH 14
#define VERTICAL_FRONT_PORCH 16
#define VERTICAL_SYNC_WIDTH 2
#define FRAME_RATE 60
```
- Define the **PanelInfo** structure.
```c++
struct PanelInfo {
uint32_t width;
uint32_t height;
uint32_t hbp;
......@@ -194,64 +222,46 @@ struct PanelInfo {
struct MipiDsiDesc mipi;
struct BlkDesc blk;
struct PwmCfg pwm;
};
/* Initialization sequence of the LCD panel */
static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A };
static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 };
static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B };
static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A };
static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C };
static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C };
static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 };
static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 };
static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 };
static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 };
static uint8_t g_payLoad10[] = { 0xb7, 0x41 };
static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 };
static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 };
static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 };
static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF };
static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 };
static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 };
static uint8_t g_payLoad17[] = { 0xc7, 0x04 };
static uint8_t g_payLoad18[] = {
};
```
- Initialize the LCD.
```c++
static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A };
static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 };
static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B };
static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A };
static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C };
static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C };
static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 };
static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 };
static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 };
static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 };
static uint8_t g_payLoad10[] = { 0xb7, 0x41 };
static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 };
static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 };
static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 };
static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF };
static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 };
static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 };
static uint8_t g_payLoad17[] = { 0xc7, 0x04 };
static uint8_t g_payLoad18[] = {
0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40,
0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52,
0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06
};
static uint8_t g_payLoad19[] = { 0x11 };
static uint8_t g_payLoad20[] = { 0x29 };
struct DsiCmdDesc g_OnCmd[] = {
{ 0x29, 0, sizeof(g_payLoad0), g_payLoad0 },
{ 0x29, 0, sizeof(g_payLoad1), g_payLoad1 },
{ 0x29, 0, sizeof(g_payLoad2), g_payLoad2 },
{ 0x29, 0, sizeof(g_payLoad3), g_payLoad3 },
{ 0x29, 0, sizeof(g_payLoad4), g_payLoad4 },
{ 0x29, 0, sizeof(g_payLoad5), g_payLoad5 },
{ 0x29, 0, sizeof(g_payLoad6), g_payLoad6 },
{ 0x29, 0, sizeof(g_payLoad7), g_payLoad7 },
{ 0x29, 0, sizeof(g_payLoad8), g_payLoad8 },
{ 0x29, 0, sizeof(g_payLoad9), g_payLoad9 },
{ 0x23, 0, sizeof(g_payLoad10), g_payLoad10 },
{ 0x29, 0, sizeof(g_payLoad11), g_payLoad11 },
{ 0x29, 0, sizeof(g_payLoad12), g_payLoad12 },
{ 0x29, 0, sizeof(g_payLoad13), g_payLoad13 },
{ 0x29, 0, sizeof(g_payLoad14), g_payLoad14 },
{ 0x29, 0, sizeof(g_payLoad15), g_payLoad15 },
{ 0x29, 0, sizeof(g_payLoad16), g_payLoad16 },
{ 0x23, 0, sizeof(g_payLoad17), g_payLoad17 },
{ 0x29, 1, sizeof(g_payLoad18), g_payLoad18 },
{ 0x05, 120, sizeof(g_payLoad19), g_payLoad19 },
{ 0x05, 120, sizeof(g_payLoad20), g_payLoad20 },
};
static DevHandle g_mipiHandle = NULL;
static DevHandle g_pwmHandle = NULL;
/* Set the status of the reset pin. */
static int32_t LcdResetOn(void)
{
};
static uint8_t g_payLoad19[] = { 0x11 };
static uint8_t g_payLoad20[] = { 0x29 };
static DevHandle g_mipiHandle = NULL;
static DevHandle g_pwmHandle = NULL;
```
- Set the status of the reset pin.
```c++
static int32_t LcdResetOn(void)
{
int32_t ret;
ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT);
if (ret != HDF_SUCCESS) {
......@@ -266,79 +276,14 @@ static int32_t LcdResetOn(void)
/* Set the delay to 20 ms. */
OsalMSleep(20);
return HDF_SUCCESS;
}
static int32_t SampleInit(void)
{
/* Open the MIPI DSI device handle. */
g_mipiHandle = MipiDsiOpen(MIPI_DSI0);
if (g_mipiHandle == NULL) {
HDF_LOGE("%s: MipiDsiOpen failure", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
```
static int32_t SampleOn(void)
{
int32_t ret;
/* Power on the LCD. */
ret = LcdResetOn();
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: LcdResetOn failure", __func__);
return HDF_FAILURE;
}
if (g_mipiHandle == NULL) {
HDF_LOGE("%s: g_mipiHandle is null", __func__);
return HDF_FAILURE;
}
/* Send the initialization sequence via MIPI. */
int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]);
int32_t i;
for (i = 0; i < count; i++) {
ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i]));
if (ret != HDF_SUCCESS) {
HDF_LOGE("MipiDsiTx failure");
return HDF_FAILURE;
}
}
/* Set MIPI to the high speed (HS) mode. */
MipiDsiSetHsMode(g_mipiHandle);
return HDF_SUCCESS;
}
/* PanelInfo structure variables */
static struct PanelInfo g_panelInfo = {
.width = WIDTH, /* width */
.height = HEIGHT, /* height */
.hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */
.hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */
.hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */
.vbp = VERTICAL_BACK_PORCH, /* vertical back porch */
.vfp = VERTICAL_FRONT_PORCH, /* vertical front porch */
.vsw = VERTICAL_SYNC_WIDTH, /* vertical sync width */
.frameRate = FRAME_RATE, /* frame rate */
.intfType = MIPI_DSI, /* panel interface type */
.intfSync = OUTPUT_USER, /* output timing type */
/* MIPI configuration */
.mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT },
/* backlight config info */
.blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL },
.pwm = { BLK_PWM1, PWM_MAX_PERIOD },
};
/* Basic APIs that need to be adapted for the chip driver */
static struct PanelData g_panelData = {
.info = &g_panelInfo,
.init = SampleInit,
.on = SampleOn,
.off = SampleOff,
.setBacklight = SampleSetBacklight,
};
/* Entry function of the chip driver */
int32_t SampleEntryInit(struct HdfDeviceObject *object)
{
- Initialize the entry function of the device driver.
```c++
int32_t SampleEntryInit(struct HdfDeviceObject *object)
{
HDF_LOGI("%s: enter", __func__);
if (object == NULL) {
HDF_LOGE("%s: param is null!", __func__);
......@@ -350,13 +295,13 @@ int32_t SampleEntryInit(struct HdfDeviceObject *object)
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
}
struct HdfDriverEntry g_sampleDevEntry = {
struct HdfDriverEntry g_sampleDevEntry = {
.moduleVersion = 1,
.moduleName = "LCD_SAMPLE",
.Init = SampleEntryInit,
};
};
HDF_INIT(g_sampleDevEntry);
```
HDF_INIT(g_sampleDevEntry);
```
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册