The Hardware Driver Foundation (HDF) is designed based on the component-based driver model. This model allows refined driver management and standardize driver development and deployment. Device drivers of the same type are placed in the same host. You can develop and deploy the drivers separately. One driver can have multiple nodes. The figure below shows the HDF 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 figure below shows the HDF driver model.
**Figure 1** HDF driver model
**Figure 1** HDF driver model


## How to Development
## How to Develop
The HDF-based driver development involves driver implementation and configuration. The procedure is as follows:
The HDF-based driver development involves driver implementation and driver configuration. The development procedure is as follows:
1. Implement a driver.<br/>
Write the driver code and register the driver entry with the HDF.
1. Implement a driver.
- Writing the driver service code
To implement a driver, compile driver service code and register a driver entry.
- Driver service code
The following is an example:
```
```
#include "hdf_device_desc.h" // Header file that describes the APIs provided by the HDF to the driver.
#include "hdf_device_desc.h" // Header file that defines the driver development APIs provided by the HDF.
#include "hdf_log.h" // Header file that describes the log APIs provided by the HDF.
#include "hdf_log.h" // Header file that defines the log APIs provided by the HDF.
#define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
#define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
// Service capabilities provided by the driver. Bind the service APIs to the HDF.
// Bind the service interface provided by the driver to the HDF.
@@ -46,8 +50,10 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -46,8 +50,10 @@ The HDF-based driver development involves driver implementation and driver confi
return;
return;
}
}
```
```
- Registering the driver entry with the HDF
- Registering the driver entry with the HDF
```
```
// Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h).
// 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 = {
struct HdfDriverEntry g_sampleDriverEntry = {
...
@@ -58,28 +64,28 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -58,28 +64,28 @@ The HDF-based driver development involves driver implementation and driver confi
.Release = HdfSampleDriverRelease,
.Release = HdfSampleDriverRelease,
};
};
// Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function first and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release the 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 the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
HDF_INIT(g_sampleDriverEntry);
HDF_INIT(g_sampleDriverEntry);
```
```
2. Build the driver.
2. Build the driver.<br/>
- LiteOS
- LiteOS<br/>
Modify **makefile** and **BUILD.gn**.
Modify **makefile** and **BUILD.gn**.
- makefile:
- **makefile**:<br/>
Use the **makefile** template provided by the HDF to compile the driver code.
Use the **makefile** template provided by the HDF to compile the driver code.
```
```
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory.
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory.
MODULE_NAME := # File to be generated.
MODULE_NAME := # File to be generated.
LOCAL_INCLUDE: = # Header file directory of the driver.
LOCAL_INCLUDE: = # Directory of the driver header files.
LOCAL_SRCS : = # Source code file of the driver.
LOCAL_SRCS : = # Source code file of the driver.
LOCAL_CFLAGS : = # Custom compilation options.
LOCAL_CFLAGS : = # Custom compilation options.
include $(HDF_DRIVER) # Import the makefile template to complete the compilation.
include $(HDF_DRIVER) # Import the makefile template to complete the compilation.
```
```
Add the path of the generated file to **hdf_lite.mk** in the **drivers/adapter/khdf/liteos** directory to link the file to the kernel image. The following is an example:
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.
```
```
...
@@ -87,7 +93,7 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -87,7 +93,7 @@ The HDF-based driver development involves driver implementation and driver confi
LIB_SUBDIRS += # Directory in which the driver code makefile is located.
LIB_SUBDIRS += # Directory in which the driver code makefile is located.
```
```
- **BUILD.gn**:
- **BUILD.gn**:<br/>
Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
...
@@ -98,18 +104,18 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -98,18 +104,18 @@ The HDF-based driver development involves driver implementation and driver confi
module_name = "xxx"
module_name = "xxx"
hdf_driver(module_name) {
hdf_driver(module_name) {
sources = [
sources = [
"xxx/xxx/xxx.c", # Source code file of the driver
"xxx/xxx/xxx.c", # Source code to compile.
]
]
public_configs = [ ":public" ] # Configuration applied to dependencies
public_configs = [ ":public" ] # Head file configuration of the dependencies.
}
}
config("public") {# Configuration of the dependencies
config("public") {# Define the head file configuration of the dependencies.
include_dirs = [
include_dirs = [
"xxx/xxx/xxx", # Directory of the dependency header file.
"xxx/xxx/xxx", # Directory of the dependency header files.
]
]
}
}
```
```
Add the directory where the **BUILD.gn** file of the driver is located to **/drivers/adapter/khdf/liteos/BUILD.gn**.
Add the **BUILD.gn** directory to **/drivers/adapter/khdf/liteos/BUILD.gn**.
```
```
...
@@ -120,7 +126,7 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -120,7 +126,7 @@ The HDF-based driver development involves driver implementation and driver confi
]
]
}
}
```
```
- Linux
- Linux<br/>
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/adapter/khdf/linux/Kconfig**.
...
@@ -142,25 +148,25 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -142,25 +148,25 @@ The HDF-based driver development involves driver implementation and driver confi
obj-y += xxx.o
obj-y += xxx.o
```
```
3. Configure the driver.
3. Configure the driver.<br/>
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/driver-hdf-manage.md).
The HDF Configuration Source (HCS) contains the source code of HDF configuration. For details about the HCS, see [Configuration Management](../driver/driver-hdf-manage.md).
The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
- (Mandatory) Driver device description
- (Mandatory) Setting the driver device description<br/>
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:
The HDF loads a driver based on the driver device description defined by the HDF. Therefore, the driver device description must be added to the **device_info.hcs** file defined by the HDF. The following is an example:
```
```
root {
root {
device_info {
device_info {
match_attr = "hdf_manager";
match_attr = "hdf_manager";
template host { // Host template. If the node (for example, sample_host) uses the default values in the template, the values of the node fields can be omitted.
template host { // Host template. If a node (for example, sample_host) uses the default values in this template, the node fields can be omitted.
hostName = "";
hostName = "";
priority = 100;
priority = 100;
uid = ""; // User ID (UID) of the user-mode process. By default, it is left empty, that is, set to the value defined for hostName, which indicates a common user.
uid = ""; // User ID (UID) of a user-mode process. It is left empty by default. If you do not set the value, this parameter will be set to the value of hostName, which indicates a common user.
gid = ""; // Group ID (GID) of the user-mode process. By default, it is left empty, that is, set to the value defined for hostName, which indicates a common user group.
gid = ""; // Group ID (GID) of a user-mode process. It is left empty by default. If you do not set the value, this parameter will be set to the value of hostName, which indicates a common user group.
caps = [""]]; // Linux capabilities of the user-mode process. It is left empty by default. Set this parameter based on service requirements.
caps = [""]]; // Linux capabilities of a user-mode process. It is left empty by default. Set this parameter based on service requirements.
template device {
template device {
template deviceNode {
template deviceNode {
policy = 0;
policy = 0;
...
@@ -174,17 +180,17 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -174,17 +180,17 @@ The HDF-based driver development involves driver implementation and driver confi
}
}
}
}
sample_host :: host{
sample_host :: host{
hostName = "host0"; // Host name. The host node is used to store a type of drivers.
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 larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence is random.
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 the user-mode process.
device_sample :: device { // Sample device node.
device_sample :: device { // Sample device node.
device0 :: deviceNode { // DeviceNode of the sample driver.
device0 :: deviceNode { // DeviceNode of the sample driver.
policy = 1; // Driver service release policy. For details, see the Driver Service Management.
policy = 1; // Policy for providing the driver service. For details, see 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 host loading sequence is random.
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; // On-demand loading of the driver. For details, see "NOTE" at the end of this section.
preload = 0; // The loading mode of the driver is on-demand loading. For details, see "NOTE" at the end of this document.
permission = 0664; // Permission for the driver to create a device node.
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.
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.
serviceName = "sample_service"; // Name of the service provided 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.
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.
}
}
}
}
...
@@ -192,18 +198,20 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -192,18 +198,20 @@ The HDF-based driver development involves driver implementation and driver confi
- **uid**, **gid**, and **caps** are startup configuration for user-mode drivers and do not need to be configured for kernel-mode drivers.
- **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
- According to the principle of least privilege for processes, **uid** and **gid** do not need to be configured for service modules. In the preceding example, **uid** and **gid** are left empty (granted with the common user rights) for sample_host.
- According to the principle of least privilege for processes, **uid** and **gid** do not need to be configured for service modules. In the preceding example, **uid** and **gid** are left empty (granted with the common user rights) for sample_host.
- If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
- If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
- The process UID is configured in **base/startup/init_lite/services/etc/passwd**, and the process GID is 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).
- 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, set **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
- If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
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).
- (Optional) Private configuration information of the driver
The following is an example of the driver private configuration:
If the driver has private configuration, you can add a driver configuration file to set default driver configuration. When loading the driver, the HDF obtains and saves the corresponding configuration in **property** of **HdfDeviceObject**, and passes the configuration to the driver through **Bind()** and **Init()** (see step 1). The following is an example of the driver configuration:
```
```
...
@@ -211,12 +219,14 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -211,12 +219,14 @@ The HDF-based driver development involves driver implementation and driver confi
SampleDriverConfig {
SampleDriverConfig {
sample_version = 1;
sample_version = 1;
sample_bus = "I2C_0";
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.
match_attr = "sample_config"; // The value must be the same as that of deviceMatchAttr in device_info.hcs.
}
}
}
}
```
```
After the configuration, add the configuration file to the board-level configuration entry file **hdf.hcs**. (You can use DevEco to perform on-click configuration. For details, see the description about the driver development suite.) The following is an example:
After the configuration, add the configuration file to the board-level configuration entry file **hdf.hcs**. (You can use DevEco to perform one-click configuration. For details, see the description about the driver development suite.)
The following is an example:
```
```
...
@@ -225,7 +235,7 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -225,7 +235,7 @@ The HDF-based driver development involves driver implementation and driver confi
@@ -239,11 +249,11 @@ The HDF-based driver development involves driver implementation and driver confi
...
@@ -239,11 +249,11 @@ The HDF-based driver development involves driver implementation and driver confi
> } DevicePreload;
> } 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** in the configuration file is set to **0 (DEVICE_PRELOAD_ENABLE)**, the driver is loaded by default during the system boot process.
>
>
> If **preload** is set to **1** (**DEVICE\_PRELOAD\_ENABLE\_STEP2**), the driver is loaded after a quick start is complete if the system supports quick start. If the system does not support quick start, the value **1** has the same meaning as **DEVICE\_PRELOAD\_ENABLE**.
> If **preload** is set to **1 (DEVICE_PRELOAD_ENABLE_STEP2)**, the driver is loaded after a quick start is complete. If the system does not support quick start, the value **1** has the same meaning as **DEVICE_PRELOAD_ENABLE**.
>
>
> If **preload** is set to **2** (**DEVICE\_PRELOAD\_DISABLE**), the driver is dynamically loaded instead of being loaded during the system boot process. When a user-mode process requests the driver service (for details, see [Driver Message Mechanism Management](driver-hdf-message-management.md)), the HDF attempts to dynamically load the driver if the driver service does not exist.
> If **preload** is set to **2 (DEVICE_PRELOAD_DISABLE)** , the driver is dynamically loaded instead of being loaded during the system boot process. When a user-mode process requests the driver service, the HDF attempts to dynamically load the driver if the driver service does not exist. For more details, see [Driver Messaging Mechanism](driver-hdf-message-management.md).
>
>
> - Sequential loading (drivers must be loaded by default)
> - Sequential loading (**preload** set to **0 (DEVICE_PRELOAD_ENABLE)**)<br/>
> In the configuration file, the **priority** field \(value range: 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.
> In the configuration file, the **priority** fields (value range: 0 to 200) determines the loading sequence of a host and a driver. For drivers in different hosts, a smaller host priority value indicates a higher driver loading priority; for drivers in the same host, a smaller driver priority value indicates a higher driver loading priority.
| struct HdfIoService \*HdfIoServiceBind(const char \*serviceName); | Obtains a driver service. The **Dispatch()** method in the driver service obtained sends messages to the driver.|
</thead>
| 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.|
<tdclass="cellrowborder"valign="top"width="53.620000000000005%"headers="mcps1.2.3.1.2 "><pid="p58272614113"><aname="p58272614113"></a><aname="p58272614113"></a>Obtains a specified driver service. After the service is obtained, the <strongid="b9799159433"><aname="b9799159433"></a><aname="b9799159433"></a>Dispatch</strong> function of the service is used to send messages to the driver.</p>
<tdclass="cellrowborder"valign="top"width="53.620000000000005%"headers="mcps1.2.3.1.2 "><pid="p18825261412"><aname="p18825261412"></a><aname="p18825261412"></a>Receives events sent by the drivers.</p>
## 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-hdf-servicemanage.md)\).
```
```
device_sample :: Device {
device_sample :: Device {
...
@@ -54,11 +35,12 @@ The message mechanism provides the following features:
...
@@ -54,11 +35,12 @@ The message mechanism provides the following features:
}
}
```
```
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.
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.
3. Implement the **Dispatch** function of the service base member **IDeviceIoService** during service implementation.
3. Implement the **Dispatch()** method of **IDeviceIoService**.
```
```
// Process messages delivered by user-level applications.
// Dispatch messages sent from the user-mode application.
The Hardware Driver Foundation \(HDF\) provides the following driver framework capabilities: driver loading, driver service management, and driver message mechanism. This unified driver architecture platform is designed to provide a more precise and efficient development environment, where you can perform one-time development and multi-system deployment.
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.
Both on-demand loading and sequential loading are supported.
- On-demand loading
## Driver Loading
Drivers can be loaded by default during the operating system \(OS\) startup or be loaded dynamically after the OS startup.
The HDF supports the following loading modes:
- Sequential loading
- On-demand loading
The driver is loaded by default during the operating system (OS) boot process or dynamically loaded after OS is started.
Drivers can be loaded based on their priorities during the OS startup.
- Sequential loading
The driver is loaded based on its priority during the OS boot process.
## Driver Service Management<a name="section12453133414412"></a>
## Driver Service Management
The HDF centrally manages driver services. You can directly obtain a specified driver service by using the API provided by the HDF.
The HDF allows centralized management of driver services. You can obtain a driver service by using the API provided by the HDF.
# HDF Development Example<a name="EN-US_TOPIC_0000001052451677"></a>
# HDF Development Example
The following example shows how to add driver configuration, compile the driver code, and implement interaction between the user-state applications and the driver.
## Compiling the Code for Interaction<a name="section6205173816412"></a>
The following is the sample code compiled based on HDF for interaction between the driver and user-state applications. You can place the code in **drivers/adapter/uhdf** for compilation. For details about the **build.gn** file, see **drivers/framework/sample/platform/uart/dev/build.gn**.
## 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**.
>The code compilation of user-state applications depends on the dynamic libraries **hdf\_core** and **osal** provided by HDF because user-state applications use the message sending interface of HDF. In the GN file, add the following dependencies:
> The user-mode application uses the message sending API of the HDF, and the compilation of the user-mode application depends on the dynamic libraries **hdf_core** and **osal** provided by the HDF. Therefore, you need to add the following dependencies to the .gn file:
# Driver Service Management<a name="EN-US_TOPIC_0000001052777057"></a>
# Driver Service Management
Driver services are objects of open capabilities provided by the HDF and are managed by the HDF in a unified manner. Using driver service management, you can release and obtain driver services.
Driver services are objects of capabilities provided by HDF driver devices to external systems and are managed by the HDF in a unified manner. Driver service management involves providing and obtaining driver services.
The HDF uses the **policy** field in the configuration file to define policies for drivers to provide services externally. The values this field are as follows:
The HDF uses the **policy** field in the configuration file to define policies for drivers to release services externally. The values and meanings of this field are as follows:
```
```
typedef enum {
typedef enum {
/* The driver does not provide services. */
/* The driver does not provide services. */
SERVICE_POLICY_NONE = 0,
SERVICE_POLICY_NONE = 0,
/* The driver provides services for kernel-space applications. */
/* The driver provides services only for kernel-mode applications. */
SERVICE_POLICY_PUBLIC = 1,
SERVICE_POLICY_PUBLIC = 1,
/* The driver provides services for both kernel- and user-space applications. */
/* The driver provides services for both kernel- and user-mode applications. */
SERVICE_POLICY_CAPACITY = 2,
SERVICE_POLICY_CAPACITY = 2,
/* The driver services are not released externally but can be subscribed to. */
/** The driver services are not provided externally but can be subscribed to. */
SERVICE_POLICY_FRIENDLY = 3,
SERVICE_POLICY_FRIENDLY = 3,
/* The driver services are private. They are neither released nor subscribed to. */
/* The driver private services cannot be provided externally or subscribed to. */
SERVICE_POLICY_PRIVATE = 4,
SERVICE_POLICY_PRIVATE = 4,
/* The service policy is incorrect. */
/** Invalid service policy. */
SERVICE_POLICY_INVALID
SERVICE_POLICY_INVALID
} ServicePolicy;
} ServicePolicy;
```
```
## When to Use<a name="section14244270117"></a>
## When to Use
The driver service management capability can be used if the driver provides capabilities using APIs.
The driver service management capability can be used if the driver provides capabilities using APIs.
## Available APIs<a name="section1432412561722"></a>
## Available APIs
The table below describes the APIs used for driver service management.
The table below describes the APIs for driver service management.
| int32_t (\*Bind)(struct HdfDeviceObject \*deviceObject); | Binds a service API to the HDF. You need to implement the **Bind()** function.|
</th>
| const struct HdfObject \*DevSvcManagerClntGetService(const char \*svcName); | Obtains a driver service.|
</tr>
| int HdfDeviceSubscribeService(<br>struct HdfDeviceObject \*deviceObject, const char \*serviceName, struct SubscriberCallback callback); | Subscribes to a driver service.|
<tdclass="cellrowborder"valign="top"width="50%"headers="mcps1.2.3.1.2 "><pid="p46015332591"><aname="p46015332591"></a><aname="p46015332591"></a>Binds a service interface to the HDF. You need to implement the <strongid="b876584084419"><aname="b876584084419"></a><aname="b876584084419"></a>Bind</strong> function.</p>
<tdclass="cellrowborder"valign="top"width="50%"headers="mcps1.2.3.1.2 "><pid="p06029334597"><aname="p06029334597"></a><aname="p06029334597"></a>Subscribes to a specified driver service.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section393515164416"></a>
The development of driver service management includes compiling, binding, obtaining, and subscribing to driver services. The details are as follows:
1. Release a driver service.
```
```
Define the driver service structure.
Define the driver service structure.
struct ISampleDriverService {
struct ISampleDriverService {
struct IDeviceIoService ioService; // The first member of the service structure must be a member of the IDeviceIoService type.
struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type.
int32_t (*ServiceA)(void); // The first service interface of the driver.
int32_t (*ServiceA)(void); // API of the first driver service.
int32_t (*ServiceB)(uint32_t inputCode); // The second service interface of the driver. The rest can be deduced by analogy.
int32_t (*ServiceB)(uint32_t inputCode); // API of the second driver service. You can add more as required.
};
};
Implementation of the driver service interface
Implement the driver service APIs.
int32_t SampleDriverServiceA(void)
int32_t SampleDriverServiceA(void)
{
{
// You need to implement the service logic.
// You need to implement the service logic.
...
@@ -86,12 +72,12 @@ The development of driver service management includes compiling, binding, obtain
...
@@ -86,12 +72,12 @@ The development of driver service management includes compiling, binding, obtain
}
}
```
```
2. Bind the driver service to the HDF and implement the **Bind** function in the **HdfDriverEntry** structure.
2.Bind the driver service to the HDF and implement the **Bind()** function in the **HdfDriverEntry** structure.
// deviceObject indicates the pointer to the device object created by the HDF for each driver. It is used to store device-related private data and service interfaces.
// 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) {
if (deviceObject == NULL) {
HDF_LOGE("Sample device object is null!");
HDF_LOGE("Sample device object is null!");
return -1;
return -1;
...
@@ -106,12 +92,11 @@ The development of driver service management includes compiling, binding, obtain
...
@@ -106,12 +92,11 @@ The development of driver service management includes compiling, binding, obtain
```
```
3. Obtain the driver service.
3. Obtain the driver service.
The driver service can be obtained by using the API or subscription mechanism provided by the HDF.
You can either use the API or subscription mechanism provided by the HDF to obtain the driver service.
- Using the API
- Using the API
Use the API provided by the HDF to obtain the driver service if the driver has been loaded.
After the driver is loaded, you can obtain the driver service using the API provided by the HDF, as shown in the following:
@@ -122,14 +107,13 @@ The development of driver service management includes compiling, binding, obtain
...
@@ -122,14 +107,13 @@ The development of driver service management includes compiling, binding, obtain
sampleService->ServiceA();
sampleService->ServiceA();
sampleService->ServiceB(5);
sampleService->ServiceB(5);
```
```
- Using the subscription mechanism
- 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 sends the driver services to the subscriber. The implementation is as follows:
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 releases the driver services to you. The implementation is as follows:
```
```
// Subscription callback function. After the subscribed drivers are loaded, the HDF releases the driver services to you using this function.
// Callback invoked to return the driver services after the subscribed driver is loaded.
// object indicates the pointer to the private data of the subscriber, and service indicates the pointer to the subscribed service.
// object is the pointer to the private data of the subscriber, and service is the pointer to the subscribed service object.
This section describes how to develop the touchscreen driver based on the input driver model. [Figure 1](#fig6251184817261) shows an overall architecture of the touchscreen driver.
This section describes how to develop the touchscreen driver based on the input driver model. [Figure 1](#fig6251184817261) shows an overall architecture of the touchscreen driver.
The input driver is developed based on the hardware driver foundation \(HDF\), platform APIs, and operating system abstraction layer \(OSAL\) APIs. It provides hardware driver capabilities through the input Hardware Driver Interfaces \(HDIs\) for upper-layer input services to control the touchscreen.
The input driver is developed based on the hardware driver foundation \(HDF\), platform APIs, and operating system abstraction layer \(OSAL\) APIs. It provides hardware driver capabilities through the input Hardware Device Interfaces \(HDIs\) for upper-layer input services to control the touchscreen.
**Figure 1** Architecture of the input driver model<aname="fig6251184817261"></a>
**Figure 1** Architecture of the input driver model<aname="fig6251184817261"></a>
...
@@ -88,7 +88,7 @@ Perform the following steps:
...
@@ -88,7 +88,7 @@ Perform the following steps:
1. Add the touchscreen driver-related descriptions.
1. Add the touchscreen driver-related descriptions.
Currently, the input driver is developed based on the HDF and is loaded and started by the HDF. Register the driver information, such as whether to load the driver and the loading priority in the configuration file. Then, the HDF starts the registered driver modules one by one. For details about the driver configuration, see [Driver Development](driver-hdf-development.md#section1969312275533).
Currently, the input driver is developed based on the HDF and is loaded and started by the HDF. Register the driver information, such as whether to load the driver and the loading priority in the configuration file. Then, the HDF starts the registered driver modules one by one. For details about the driver configuration, see [Driver Development](driver-hdf-development.md#how-to-develop).
2. Complete the board-level configuration and private data configuration of the touchscreen.
2. Complete the board-level configuration and private data configuration of the touchscreen.
...
@@ -96,7 +96,7 @@ Perform the following steps:
...
@@ -96,7 +96,7 @@ Perform the following steps:
3. Implement differentiated adaptation APIs of the touchscreen.
3. Implement differentiated adaptation APIs of the touchscreen.
Use the platform APIs to perform operations for the reset pins, interrupt pins, and power based on the communications interfaces designed for boards. For details about the GPIO-related operations, see [GPIO](driver-platform-gpio-des.md#section1635911016188).
Use the platform APIs to perform operations for the reset pins, interrupt pins, and power based on the communications interfaces designed for boards. For details about the GPIO-related operations, see [GPIO](driver-platform-gpio-des.md#overview).
## Development Example<a name="section263714411191"></a>
## Development Example<a name="section263714411191"></a>
In the Hardware Driver Foundation \(HDF\), the Universal Asynchronous Receiver/Transmitter \(UART\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
In the Hardware Driver Foundation \(HDF\), the Universal Asynchronous Receiver/Transmitter \(UART\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
...
@@ -186,7 +180,7 @@ The UART module adaptation involves the following steps:
...
@@ -186,7 +180,7 @@ The UART module adaptation involves the following steps: