diff --git a/en/device-dev/driver/driver-hdf-development.md b/en/device-dev/driver/driver-hdf-development.md
index a690d42bf3ebd1c47689c6f8eb72c52379701e4e..306da57b83bbf185eab2b4365d7585dd06533991 100644
--- a/en/device-dev/driver/driver-hdf-development.md
+++ b/en/device-dev/driver/driver-hdf-development.md
@@ -3,34 +3,34 @@
## Driver Model
-The Hardware Driver Foundation (HDF) is designed upon a component-based driver model. This model enables refined driver management and streamlines driver development and deployment. In the HDF, the same type of device drivers are placed in a host. You can develop and deploy the drivers separately. One driver can have multiple nodes.
+The Hardware Driver Foundation (HDF) is designed upon a component-based driver model. This model enables refined driver management and streamlines driver development and deployment. In the HDF, the same type of device drivers are placed in a host. You can develop and deploy the drivers separately. One driver can have multiple nodes.
The figure below shows the HDF driver model.
-**Figure 1** HDF driver model
+ **Figure 1** HDF driver model
![](figures/hdf-driver-model.png)
## How to Develop
-The HDF-based driver development involves driver implementation and configuration. The procedure is as follows:
+The HDF-based driver development process involves driver implementation, build, and configuration. The procedure is as follows:
1. Implement a driver.
-
+
Write the driver code and register the driver entry with the HDF.
-
- - Writing the driver service code
-
- The following is an example:
+
+ - Write the driver service code.
+ The following is an example:
+
```
- #include "hdf_device_desc.h" // Header file that defines the driver development APIs provided by the HDF.
- #include "hdf_log.h" // Header file that defines the log APIs provided by the HDF.
+ #include "hdf_device_desc.h" // Header file that defines the driver development APIs provided by the HDF.
+ #include "hdf_log.h" // Header file that defines the log APIs provided by the HDF.
#define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
- // Bind the service interface provided by the driver to the HDF.
+ // Bind the service APIs provided by the driver to the HDF.
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
HDF_LOGD("Sample driver bind success");
@@ -51,7 +51,8 @@ The HDF-based driver development involves driver implementation and configuratio
return;
}
```
- - Registering the driver entry with the HDF
+
+ - Register 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).
@@ -66,114 +67,115 @@ The HDF-based driver development involves driver implementation and configuratio
// Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
HDF_INIT(g_sampleDriverEntry);
```
-
+
2. Build the driver.
-
+
- LiteOS
-
- Modify **makefile** and **BUILD.gn**.
-
- - **Makefile**:
-
- Use the **makefile** template provided by the HDF to compile the driver code.
-
-
- ```
- include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory.
- MODULE_NAME := # File to be generated.
- LOCAL_INCLUDE: = # Directory of the driver header files.
- LOCAL_SRCS : = # Source code file of the driver.
- LOCAL_CFLAGS : = # Custom compilation options.
- include $(HDF_DRIVER) # Import the Makefile template to complete the 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:
-
-
- ```
- LITEOS_BASELIB += -lxxx # Static library generated by the link.
- LIB_SUBDIRS += # Directory in which Makefile is located.
- ```
-
- - **BUILD.gn**:
-
- Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
-
-
- ```
- import("//build/lite/config/component/lite_component.gni")
- import("//drivers/adapter/khdf/liteos/hdf.gni")
- module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
- module_name = "xxx"
- hdf_driver(module_name) {
- sources = [
- "xxx/xxx/xxx.c", # Source code to compile.
- ]
- public_configs = [ ":public" ] # Head file configuration of the dependencies.
- }
- config("public") {# Define the head file configuration of the dependencies.
- include_dirs = [
- "xxx/xxx/xxx", # Directory of the dependency header files.
- ]
- }
- ```
-
- Add the **BUILD.gn** directory to **/drivers/adapter/khdf/liteos/BUILD.gn**.
-
-
- ```
- group("liteos") {
- public_deps = [ ":$module_name" ]
- deps = [
- "xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos.
- ]
- }
- ```
-
+
+ Modify **Makefile** and **BUILD.gn** files.
+
+ - **Makefile**:
+
+ 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.
+ 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.
+ ```
+
+ Add the path of the generated file to **hdf_lite.mk** in the **drivers/adapter/khdf/liteos** directory to link the file to the kernel image. The following is an example:
+
+
+ ```
+ LITEOS_BASELIB += -lxxx # Static library generated by the link.
+ LIB_SUBDIRS += # Directory in which Makefile is located.
+ ```
+
+ - **BUILD.gn**:
+
+ Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
+
+
+ ```
+ import("//build/lite/config/component/lite_component.gni")
+ import("//drivers/adapter/khdf/liteos/hdf.gni")
+ module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
+ module_name = "xxx"
+ hdf_driver(module_name) {
+ sources = [
+ "xxx/xxx/xxx.c", # Source code to compile.
+ ]
+ public_configs = [ ":public" ] # Head file configuration of the dependencies.
+ }
+ config("public") { # Define the head file configuration of the dependencies.
+ include_dirs = [
+ "xxx/xxx/xxx", # Directory of dependency header files.
+ ]
+ }
+ ```
+
+ Add the **BUILD.gn** directory to **/drivers/adapter/khdf/liteos/BUILD.gn**.
+
+
+ ```
+ group("liteos") {
+ public_deps = [ ":$module_name" ]
+ deps = [
+ "xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos.
+ ]
+ }
+ ```
- Linux
- To define the driver control macro, add the **Kconfig** file to the driver directory **xxx** and add the path of the **Kconfig** file to **drivers/adapter/khdf/linux/Kconfig**.
-
-
- ```
- source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
- ```
+ 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**.
- Add the driver directory to **drivers/adapter/khdf/linux/Makefile**.
-
-
- ```
- obj-$(CONFIG_DRIVERS_HDF) += xxx/
- ```
+
+ ```
+ source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
+ ```
- Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the file.
-
-
- ```
- obj-y += xxx.o
- ```
-
-3. Configure the driver.
+ Add the driver directory to **drivers/adapter/khdf/linux/Makefile**.
+
+
+ ```
+ obj-$(CONFIG_DRIVERS_HDF) += xxx/
+ ```
+
+ Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
+
+
+ ```
+ obj-y += xxx.o
+ ```
+
+3. Configure the driver.
The HDF Configuration Source (HCS) contains the source code of HDF configuration. For details about the HCS, see [Configuration Management](../driver/driver-hdf-manage.md).
The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
- - (Mandatory) Setting the driver device description
+ - (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.
+ The following is an example:
+
```
root {
device_info {
match_attr = "hdf_manager";
- template host { // Host template. If a node (for example, sample_host) uses the default values in this template, 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 = "";
priority = 100;
- 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 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 a user-mode process. It is left empty by default. Set this parameter based on service requirements.
+ uid = ""; // User ID (UID) of the 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. 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.
template device {
template deviceNode {
policy = 0;
@@ -192,11 +194,11 @@ The HDF-based driver development involves driver implementation and configuratio
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // Linux capabilities of the user-mode process.
device_sample :: device { // Sample device node.
device0 :: deviceNode { // DeviceNode of the sample driver.
- policy = 1; // Policy for publishing the driver service. For details, see Driver Service Management.
+ policy = 1; // Policy for publishing the driver service. For details, see Driver Service Management.
priority = 100; // Driver startup priority (0-200). A smaller value indicates a higher priority. The default value 100 is recommended. The drivers with the same priority start based on the time when the priority was configured. The driver configured first starts first.
- preload = 0; // The loading mode of the driver is on-demand loading. For details, see "NOTE" at the end of this document.
+ 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.
+ moduleName = "sample_driver"; // Driver name. The value of this field must be the same as that of moduleName in the HdfDriverEntry structure.
serviceName = "sample_service"; // Name of the service published by the driver. The service name must be unique.
deviceMatchAttr = "sample_config"; // Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
}
@@ -205,49 +207,55 @@ The HDF-based driver development involves driver implementation and configuratio
}
}
```
- ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**
-
- - **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
-
- - According to the principle of least privilege for processes, **uid** and **gid** do not need to be configured for service modules. In the preceding example, **uid** and **gid** are left empty (granted with the common user rights) for sample_host.
-
- - If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
-
- - The process UIDs are configured in **base/startup/init_lite/services/etc/passwd**, and the process GIDs are configured in **base/startup/init_lite/services/etc/group**. For details, see [Adding a System Service User Group]( https://gitee.com/openharmony/startup_init_lite/wikis).
+
+ > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+ >
+ > - **uid**, **gid**, and **caps** are startup parameters for user-mode drivers only.
+ >
+ > - According to the principle of least privilege for processes, **uid** and **gid** do not need to be configured for service modules. In the preceding example, **uid** and **gid** are left empty (granted with the common user rights) for sample_host.
+ >
+ > - If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
+ >
+ > - The process UIDs are configured in **base/startup/init_lite/services/etc/passwd**, and the process GIDs are configured in **base/startup/init_lite/services/etc/group**. For details, see [Adding a System Service User Group]( https://gitee.com/openharmony/startup_init_lite/wikis).
+ >
+ > - If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
- - If CAP_DAC_OVERRIDE needs to be configured for a service module, enter **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
- - (Optional) Setting driver private information
+ - (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).
- The following is an example of the driver private configuration:
-
- ```
- root {
+ The following is an example of the driver private configuration:
+
+ ```
+ root {
SampleDriverConfig {
sample_version = 1;
sample_bus = "I2C_0";
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 one-click configuration. For details, see the description about the driver development suite.)
+ ```
+
+ After the configuration, add the configuration file to the board-level configuration entry file **hdf.hcs**. (You can use DevEco to perform one-click configuration. For details, see the description about the driver development suite.)
+
+ The following is an example:
+
+ ```
+ #include "device_info/device_info.hcs"
+ #include "sample/sample_config.hcs"
+ ```
+
+
- The following is an example:
-
- ```
- #include "device_info/device_info.hcs"
- #include "sample/sample_config.hcs"
- ```
+
-> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Drivers can be loaded on demand or in sequence.
>
> - On-demand loading
->
+>
> ```
> typedef enum {
> DEVICE_PRELOAD_ENABLE = 0,
@@ -257,11 +265,12 @@ The HDF-based driver development involves driver implementation and configuratio
> } 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 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, 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).
+> - 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 (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.
+> - 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.
diff --git a/en/device-dev/driver/driver-hdf-overview.md b/en/device-dev/driver/driver-hdf-overview.md
index 14f93df86d6e03a279e55699fe48deab75a7d7b3..451a190bc027610966bafeb7bef011fabc3ff495 100644
--- a/en/device-dev/driver/driver-hdf-overview.md
+++ b/en/device-dev/driver/driver-hdf-overview.md
@@ -11,9 +11,11 @@ The Hardware Driver Foundation (HDF) provides driver framework capabilities incl
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.
- Sequential loading
+
The driver is loaded based on its priority during the OS boot process.
diff --git a/en/device-dev/driver/driver-hdf-servicemanage.md b/en/device-dev/driver/driver-hdf-servicemanage.md
index e2d273ca2bc999b6b8e3e84aa57887f942f77393..9cb526b98bb33b6cabc4af87fb17b45760a83bdb 100644
--- a/en/device-dev/driver/driver-hdf-servicemanage.md
+++ b/en/device-dev/driver/driver-hdf-servicemanage.md
@@ -4,10 +4,10 @@
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 publishing and obtaining driver services.
-The HDF uses the **policy** field in the configuration file to define policies for drivers to publish services externally. The values this field are as follows:
+The HDF uses the **policy** field in the configuration file to define policies for a driver to provide services externally. The values this field are as follows:
+
-
```
typedef enum {
/* The driver does not provide services. */
@@ -37,28 +37,28 @@ The table below describes the APIs for driver service management.
**Table 1** APIs for driver service management
-| API| Description|
+| API| Description|
| -------- | -------- |
-| int32_t (\*Bind)(struct HdfDeviceObject \*deviceObject); | Binds a service API to the HDF. You need to implement the **Bind()** function.|
-| const struct HdfObject \*DevSvcManagerClntGetService(const char \*svcName); | Obtains a driver service.|
-| int HdfDeviceSubscribeService(
struct HdfDeviceObject \*deviceObject, const char \*serviceName, struct SubscriberCallback callback); | Subscribes to a driver service.|
+| int32_t (\*Bind)(struct HdfDeviceObject \*deviceObject) | Binds a service API to the HDF. You need to implement the **Bind()** function.|
+| const struct HdfObject \*DevSvcManagerClntGetService(const char \*svcName)| Obtains a driver service.|
+|int HdfDeviceSubscribeService(struct HdfDeviceObject \*deviceObject, const char \*serviceName, struct SubscriberCallback callback) | Subscribes to a driver service.|
## How to Develop
The development procedure is as follows:
-1. Define the services to be provided by the driver.
-
+1. Define the services to be published by the driver.
+
```
- Define the driver service structure.
+ // Define the driver service structure.
struct ISampleDriverService {
- struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type.
+ struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type.
int32_t (*ServiceA)(void); // API of the first driver service.
int32_t (*ServiceB)(uint32_t inputCode); // API of the second driver service. You can add more as required.
};
- Implement the driver service APIs.
+ // Implement the driver service APIs.
int32_t SampleDriverServiceA(void)
{
// You need to implement the service logic.
@@ -73,7 +73,7 @@ The development procedure is as follows:
```
2. Bind the driver service to the HDF and implement the **Bind()** function in the **HdfDriverEntry** structure.
-
+
```
int32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
{
@@ -92,52 +92,61 @@ The development procedure is as follows:
```
3. Obtain the driver service.
+
The driver service can be obtained by using the API or subscription mechanism provided by the HDF.
- Using the API
- Use the API provided by the HDF to obtain the driver service if the driver has been loaded.
-
-
- ```
- const struct ISampleDriverService *sampleService =
- (const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
- if (sampleService == NULL) {
- return -1;
- }
- sampleService->ServiceA();
- sampleService->ServiceB(5);
- ```
+
+ Use the API provided by the HDF to obtain the driver service if the driver has been loaded.
+
+ ```
+ ```
+ const struct ISampleDriverService *sampleService =
+ (const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
+ if (sampleService == NULL) {
+ return -1;
+ }
+ 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 sends the driver services to the subscriber. The implementation is as follows:
-
-
- ```
- // Callback invoked to return the driver services 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;
- }
- sampleService->ServiceA();
- sampleService->ServiceB(5);
- }
- // Implement the subscription process.
- int32_t TestDriverInit(struct HdfDeviceObject *deviceObject)
- {
- if (deviceObject == NULL) {
- HDF_LOGE("Test driver init failed, deviceObject is null!");
- return -1;
- }
- struct SubscriberCallback callBack;
- callBack.deviceObject = deviceObject;
- callBack.OnServiceConnected = TestDriverSubCallBack;
- int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
- if (ret != 0) {
- HDF_LOGE("Test driver subscribe sample driver failed!");
- }
- return ret;
- }
- ```
+
+ 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.
+
+ The implementation is as follows:
+
+ ```
+ // Callback invoked to return the driver services 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;
+ }
+ sampleService->ServiceA();
+ sampleService->ServiceB(5);
+ }
+ // Implement the subscription process.
+ int32_t TestDriverInit(struct HdfDeviceObject *deviceObject)
+ {
+ if (deviceObject == NULL) {
+ HDF_LOGE("Test driver init failed, deviceObject is null!");
+ return -1;
+ }
+ struct SubscriberCallback callBack;
+ callBack.deviceObject = deviceObject;
+ callBack.OnServiceConnected = TestDriverSubCallBack;
+ int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
+ if (ret != 0) {
+ HDF_LOGE("Test driver subscribe sample driver failed!");
+ }
+ return ret;
+ }
+ ```
+
+
+