1e41f4b71Sopenharmony_ci# HDF Driver Coding Guide 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## About This Document 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Purpose 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciOpenHarmony aims to build an open, distributed OS framework for smart IoT devices in the full-scenario, full-connectivity, and full-intelligence era. It has the following technical features: hardware collaboration for resource sharing, one-time development for multi-device deployment, and a unified OS for flexible deployment. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciThe Hardware Driver Foundation (HDF) provides the following driver framework capabilities: driver loading, driver service management, and driver message mechanism. This unified driver architecture system is designed to provide a more precise and efficient development environment, where you can perform one-time driver development for multi-system deployment. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciAs such, certain coding specifications are required for the OpenHarmony driver implemented based on the HDF. This document stipulates the specifications on the driver code, helping you improve code standardization and portability. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci## Coding Guide 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci### General Principles 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci#### [Rule] Use the capabilities provided by the HDF to implement drivers. 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci[Description] The HDF supports driver loading, driver service management, and driver message mechanism. It provides the Operating System Abstraction Layer (OSAL) and Platform Abstraction Layer (PAL) to support cross-system and cross-platform driver deployment. It also provides capabilities such as driver model abstraction, common tools, and peripheral component framework. You should develop drivers based on these capabilities to ensure that the drivers can be deployed on various devices powered by OpenHarmony. 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci#### [Rule] Follow this coding guide to develop drivers that can run in both the kernel space and user space. 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci[Description] Kernel-mode drivers are different from user-mode drivers in essence. They apply to different use cases. You must follow this guide during service design and development and use the HDF OSAL and PAL to shield the differences, so as to ensure that the drivers can run in both the kernel space and user space. 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci#### [Rec] Include the drivers/framework/include directory instead of a subdirectory in the build script. 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci[Description] The **drivers/framework/include** directory is the root directory of the header file exposed by the HDF externally. This directory contains multiple subdirectories to represent different modules such as the core framework, OSAL, and PAL. When using a header file, you are advised to include the **drivers/framework/include** directory in the build script. This avoids repeated inclusion when the script is referenced in the code. 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci[Example] 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci```gn 32e41f4b71Sopenharmony_ciconfig("xxxx_private_config") { 33e41f4b71Sopenharmony_ci include_dirs = [ 34e41f4b71Sopenharmony_ci "//drivers/framework/include", 35e41f4b71Sopenharmony_ci "//drivers/framework/include/core", # Not recommended. 36e41f4b71Sopenharmony_ci ] 37e41f4b71Sopenharmony_ci} 38e41f4b71Sopenharmony_ci``` 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci```c 41e41f4b71Sopenharmony_ci#include <core/hdf_device_desc.h> 42e41f4b71Sopenharmony_ci#include <hdf_device_desc.h> // Not recommended. 43e41f4b71Sopenharmony_ci``` 44e41f4b71Sopenharmony_ci 45e41f4b71Sopenharmony_ci### HDF Core Framework 46e41f4b71Sopenharmony_ci 47e41f4b71Sopenharmony_ci#### [Rule] Implement the Bind, Init, and Release methods based on the responsibility definitions in the HdfDriverEntry object. 48e41f4b71Sopenharmony_ci 49e41f4b71Sopenharmony_ci[Description] The **HdfDriverEntry** object is the entry of an HDF driver. The **Bind**, **Init**, and **Release** methods have their own responsibilities. You must implement the corresponding functions based on the responsibilities. 50e41f4b71Sopenharmony_ci 51e41f4b71Sopenharmony_ci```c 52e41f4b71Sopenharmony_cistruct HdfDriverEntry g_sampleDriverEntry = { 53e41f4b71Sopenharmony_ci .moduleVersion = 1, 54e41f4b71Sopenharmony_ci .moduleName = "sample_driver", 55e41f4b71Sopenharmony_ci .Bind = SampleDriverBind, // Responsibility: Bind the service interface provided by the driver to the HDF. 56e41f4b71Sopenharmony_ci .Init = SampleDriverInit, // Responsibility: Initialize the driver service. 57e41f4b71Sopenharmony_ci .Release = SampleDriverRelease, // Responsibility: Release driver resources. It is invoked when an exception occurs. 58e41f4b71Sopenharmony_ci}; 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ciHDF_INIT(g_sampleDriverEntry); 61e41f4b71Sopenharmony_ci``` 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci#### [Rule] The first member in the driver service structure must be of the IDeviceIoService type. 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci[Description] The first member of the service interface defined by the driver must be of the **IDeviceIoService** type. 66e41f4b71Sopenharmony_ci 67e41f4b71Sopenharmony_ci[Example] 68e41f4b71Sopenharmony_ci 69e41f4b71Sopenharmony_ci```c 70e41f4b71Sopenharmony_cistruct ISampleDriverService { 71e41f4b71Sopenharmony_ci struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type. 72e41f4b71Sopenharmony_ci int32_t (*FunctionA)(void); // The first service interface of the driver. 73e41f4b71Sopenharmony_ci int32_t (*FunctionB)(uint32_t inputCode); // The second service interface of the driver. More service interfaces can be added here. 74e41f4b71Sopenharmony_ci}; 75e41f4b71Sopenharmony_ci``` 76e41f4b71Sopenharmony_ci 77e41f4b71Sopenharmony_ci[Example] 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ci```c 80e41f4b71Sopenharmony_cistruct ISampleDriverService { 81e41f4b71Sopenharmony_ci struct IDeviceIoService ioService; // The first member must be of the IDeviceIoService type. 82e41f4b71Sopenharmony_ci void *instance; // A service instance can be encapsulated here to provide service interfaces. 83e41f4b71Sopenharmony_ci}; 84e41f4b71Sopenharmony_ci``` 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ci#### [Rule] All driver service interfaces must be bound using the Bind method of the HdfDriverEntry object. All service interfaces must be defined. They cannot be defined as null. 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci[Description] The service interfaces defined by the driver are exposed externally. If a service interface is not defined or is defined as null, exceptions may occur during external invocation. 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci[Example] 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci```c 93e41f4b71Sopenharmony_ciint32_t SampleDriverBind(struct HdfDeviceObject *deviceObject) 94e41f4b71Sopenharmony_ci{ 95e41f4b71Sopenharmony_ci static struct ISampleDriverService sampleDriver = { 96e41f4b71Sopenharmony_ci .FunctionA = SampleDriverServiceA, 97e41f4b71Sopenharmony_ci .FunctionB = NULL, // The service interface cannot be defined as null. 98e41f4b71Sopenharmony_ci }; 99e41f4b71Sopenharmony_ci // Bind ioService to the device object created by the HDF. 100e41f4b71Sopenharmony_ci deviceObject->service = &sampleDriver.ioService; 101e41f4b71Sopenharmony_ci return HDF_SUCCESS; 102e41f4b71Sopenharmony_ci} 103e41f4b71Sopenharmony_ci``` 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci#### [Rec] Call the HdfDeviceSetClass interface in the Init method of the HdfDriverEntry object to define the driver type. 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci[Description] Based on the driver type, you can classify the drivers of the current device and query the driver capabilities of the current device. For better driver management, you are advised to call **HdfDeviceSetClass** to set the driver type. 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci[Example] 110e41f4b71Sopenharmony_ci 111e41f4b71Sopenharmony_ci```c 112e41f4b71Sopenharmony_ciint32_t SampleDriverInit(struct HdfDeviceObject *deviceObject) 113e41f4b71Sopenharmony_ci{ 114e41f4b71Sopenharmony_ci // Set the driver type to DISPLAY. 115e41f4b71Sopenharmony_ci if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_DISPLAY)) { 116e41f4b71Sopenharmony_ci HDF_LOGE("HdfDeviceSetClass failed"); 117e41f4b71Sopenharmony_ci return HDF_FAILURE; 118e41f4b71Sopenharmony_ci } 119e41f4b71Sopenharmony_ci return HDF_SUCCESS; 120e41f4b71Sopenharmony_ci} 121e41f4b71Sopenharmony_ci``` 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ci### HCS 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ciHDF Configuration Source (HCS) describes the configuration source code of the HDF in the form of key-value pairs. It decouples configuration code from driver code, making it easy for you to manage the driver configuration. 126e41f4b71Sopenharmony_ci 127e41f4b71Sopenharmony_ciThe driver configuration consists of the driver device description defined by the HDF and the private configuration of a driver. 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci**Driver Device Description** 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ciThe driver loading information required by the HDF comes from the driver device description. Therefore, you must add the driver device description to the **device_info.hcs** file defined by the HDF. 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci#### [Rule] Before configuring a driver, determine the hardware to which the driver belongs and the deployment mode, and plan the directories and files to be configured. 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci[Description] In the **vendor** directory of the OpenHarmony source code, plan the directories based on the chip vendor, development board, and configuration. The HDF driver configuration is stored in the **hdf\_config** directory. According to the hardware specifications, the **hdf\_config** directory stores kernel-mode configuration information or both kernel- and user-mode configuration information. You should determine the directory where the driver is to be configured based on the driver hardware and deployment mode. 136e41f4b71Sopenharmony_ci 137e41f4b71Sopenharmony_ci[Example] 138e41f4b71Sopenharmony_ci 139e41f4b71Sopenharmony_ci```bash 140e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus/hdf_config # Directory for storing the kernel-mode configuration file. There are no user-mode configuration files. 141e41f4b71Sopenharmony_ci 142e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf # Directory for storing the kernel-mode configuration file. 143e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/uhdf # Directory for storing the user-mode configuration file. 144e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/device_info/device_info.hcs # Device description file of the kernel-mode driver. 145e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/lcd/lcd_config.hcs # Private configuration file of the kernel-mode driver. 146e41f4b71Sopenharmony_ci``` 147e41f4b71Sopenharmony_ci 148e41f4b71Sopenharmony_ci#### [Rule] Use existing configuration information and inherit existing configuration templates during driver configuration. 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci[Description] The **host**, **device**, and **deviceNode** templates have been configured in the **device_info.hcs** file. When configuring a driver, make full use of the existing configuration information and inherit HCS features to minimize your configuration workload. 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ci[Example] 153e41f4b71Sopenharmony_ci 154e41f4b71Sopenharmony_ci``` 155e41f4b71Sopenharmony_ciroot { 156e41f4b71Sopenharmony_ci device_info { 157e41f4b71Sopenharmony_ci match_attr = "hdf_manager"; 158e41f4b71Sopenharmony_ci template host { // host template 159e41f4b71Sopenharmony_ci hostName = ""; 160e41f4b71Sopenharmony_ci priority = 100; // Host startup priority. The value ranges from 0 to 200. A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence cannot be ensured. 161e41f4b71Sopenharmony_ci template device { // device template 162e41f4b71Sopenharmony_ci template deviceNode { // deviceNode template 163e41f4b71Sopenharmony_ci policy = 0; // Policy for publishing drive services. 164e41f4b71Sopenharmony_ci priority = 100; // Driver startup priority. The value ranges from 0 to 200. A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the device loading sequence cannot be ensured. 165e41f4b71Sopenharmony_ci preload = 0; // The driver is loaded as required. 166e41f4b71Sopenharmony_ci permission = 0664; // Permission for the driver to create a device node. 167e41f4b71Sopenharmony_ci moduleName = ""; 168e41f4b71Sopenharmony_ci serviceName = ""; 169e41f4b71Sopenharmony_ci deviceMatchAttr = ""; 170e41f4b71Sopenharmony_ci } 171e41f4b71Sopenharmony_ci } 172e41f4b71Sopenharmony_ci } 173e41f4b71Sopenharmony_ci // To use the default values in the template, the node fields can be not included. 174e41f4b71Sopenharmony_ci sample_host :: host { // sample_host inherits the host template. 175e41f4b71Sopenharmony_ci hostName = "host0"; // Host name. The host node is a container used to store a type of drivers. 176e41f4b71Sopenharmony_ci device_sample :: device { // device_sample inherits the device template. 177e41f4b71Sopenharmony_ci device0 :: deviceNode { // device0 inherits the deviceNode template. 178e41f4b71Sopenharmony_ci policy = 1; // Overwrite the policy in the template. 179e41f4b71Sopenharmony_ci moduleName = "sample_driver"; // Driver name. The value of this field must be the same as that of moduleName in the HdfDriverEntry structure. 180e41f4b71Sopenharmony_ci serviceName = "sample_service"; // Service name of the driver, which must be unique. 181e41f4b71Sopenharmony_ci 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. 182e41f4b71Sopenharmony_ci } 183e41f4b71Sopenharmony_ci } 184e41f4b71Sopenharmony_ci } 185e41f4b71Sopenharmony_ci } 186e41f4b71Sopenharmony_ci} 187e41f4b71Sopenharmony_ci``` 188e41f4b71Sopenharmony_ci 189e41f4b71Sopenharmony_ci#### [Rule] Use the defined types during driver model design and classification. Do not configure hosts and devices repeatedly. 190e41f4b71Sopenharmony_ci 191e41f4b71Sopenharmony_ci[Description] The HDF places the same type of devices in the same host. You can develop and deploy the driver functionalities of the host by layer, so that one driver has multiple nodes. The following figure shows the HDF driver model. 192e41f4b71Sopenharmony_ci 193e41f4b71Sopenharmony_ci 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ciPlace devices of the same type in the same host. When adding a device, check whether the host of the same type already exists. If such a host already exists, configure the device in the host. Do not configure the same host again. A device belongs to only one driver. Therefore, do not configure the same device in different hosts. 196e41f4b71Sopenharmony_ci 197e41f4b71Sopenharmony_ci#### [Rule] Set publication policies for driver services based on service rules. 198e41f4b71Sopenharmony_ci 199e41f4b71Sopenharmony_ci[Description] The driver service is the object of capabilities provided by the driver to external systems and is managed by the HDF in a unified manner. The HDF uses the **policy** field in the configuration file to define policies for drivers to publish services externally. The values and meanings of this field are as follows: 200e41f4b71Sopenharmony_ci 201e41f4b71Sopenharmony_ci```c 202e41f4b71Sopenharmony_citypedef enum { 203e41f4b71Sopenharmony_ci /* The driver does not provide services.*/ 204e41f4b71Sopenharmony_ci SERVICE_POLICY_NONE = 0, 205e41f4b71Sopenharmony_ci /* The driver provides services for kernel-space applications. */ 206e41f4b71Sopenharmony_ci SERVICE_POLICY_PUBLIC = 1, 207e41f4b71Sopenharmony_ci /* The driver provides services for both kernel- and user-space applications. */ 208e41f4b71Sopenharmony_ci SERVICE_POLICY_CAPACITY = 2, 209e41f4b71Sopenharmony_ci /** Driver services are not published externally but can be subscribed to. */ 210e41f4b71Sopenharmony_ci SERVICE_POLICY_FRIENDLY = 3, 211e41f4b71Sopenharmony_ci /* Driver services are not published externally and cannot be subscribed to. */ 212e41f4b71Sopenharmony_ci SERVICE_POLICY_PRIVATE = 4, 213e41f4b71Sopenharmony_ci /** Invalid policy. */ 214e41f4b71Sopenharmony_ci SERVICE_POLICY_INVALID 215e41f4b71Sopenharmony_ci} ServicePolicy; 216e41f4b71Sopenharmony_ci``` 217e41f4b71Sopenharmony_ci 218e41f4b71Sopenharmony_ciYou must set the policies based on service rules. Do not set unnecessary policies, for example, setting user-mode publication policies for kernel-mode drivers. 219e41f4b71Sopenharmony_ci 220e41f4b71Sopenharmony_ci[Example] 221e41f4b71Sopenharmony_ci 222e41f4b71Sopenharmony_ci``` 223e41f4b71Sopenharmony_ciroot { 224e41f4b71Sopenharmony_ci device_info { 225e41f4b71Sopenharmony_ci sample_host { 226e41f4b71Sopenharmony_ci sample_device { 227e41f4b71Sopenharmony_ci device0 { 228e41f4b71Sopenharmony_ci policy = 1; // The driver provides services for kernel-space applications. 229e41f4b71Sopenharmony_ci ... 230e41f4b71Sopenharmony_ci } 231e41f4b71Sopenharmony_ci } 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci } 234e41f4b71Sopenharmony_ci} 235e41f4b71Sopenharmony_ci``` 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ci#### [Rule] The permission to create device nodes for a driver must match the publication policy of the driver. 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci[Description] In the **device_info.hcs** file, the **permission** field specifies the permission used by the driver to create a device node. This field is a 4-digit octal number and uses the Unix file permissions, for example, 0644. This field takes effect only when the driver provides services for user-space applications (policy = 2). 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ciYou must ensure that the publication policy of the driver service matches the device node permission. Otherwise, access to the driver service may fail or the permission of the device node may be inappropriate. 242e41f4b71Sopenharmony_ci 243e41f4b71Sopenharmony_ci[Example] 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci``` 246e41f4b71Sopenharmony_ciroot { 247e41f4b71Sopenharmony_ci device_info { 248e41f4b71Sopenharmony_ci sample_host { 249e41f4b71Sopenharmony_ci sample_device { 250e41f4b71Sopenharmony_ci device0 { 251e41f4b71Sopenharmony_ci policy = 2; // The driver provides services for both kernel- and user-space applications. 252e41f4b71Sopenharmony_ci permission = 0640; // Recommended value 253e41f4b71Sopenharmony_ci ... 254e41f4b71Sopenharmony_ci } 255e41f4b71Sopenharmony_ci } 256e41f4b71Sopenharmony_ci } 257e41f4b71Sopenharmony_ci } 258e41f4b71Sopenharmony_ci} 259e41f4b71Sopenharmony_ci``` 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ci[Counterexample] 262e41f4b71Sopenharmony_ci 263e41f4b71Sopenharmony_ci``` 264e41f4b71Sopenharmony_ciroot { 265e41f4b71Sopenharmony_ci device_info { 266e41f4b71Sopenharmony_ci sample_host { 267e41f4b71Sopenharmony_ci sample_device { 268e41f4b71Sopenharmony_ci device0 { 269e41f4b71Sopenharmony_ci policy = 2; // The driver provides services for both kernel- and user-space applications. 270e41f4b71Sopenharmony_ci permission = 0777; // Excessive permission. 271e41f4b71Sopenharmony_ci ... 272e41f4b71Sopenharmony_ci } 273e41f4b71Sopenharmony_ci } 274e41f4b71Sopenharmony_ci } 275e41f4b71Sopenharmony_ci } 276e41f4b71Sopenharmony_ci} 277e41f4b71Sopenharmony_ci``` 278e41f4b71Sopenharmony_ci 279e41f4b71Sopenharmony_ci[Counterexample] 280e41f4b71Sopenharmony_ci 281e41f4b71Sopenharmony_ci``` 282e41f4b71Sopenharmony_ciroot { 283e41f4b71Sopenharmony_ci device_info { 284e41f4b71Sopenharmony_ci sample_host { 285e41f4b71Sopenharmony_ci sample_device { 286e41f4b71Sopenharmony_ci device0 { 287e41f4b71Sopenharmony_ci policy = 1; // The driver provides services for kernel-space applications but does not create a device node. 288e41f4b71Sopenharmony_ci permission = 0640; // Redundancy configuration 289e41f4b71Sopenharmony_ci ... 290e41f4b71Sopenharmony_ci } 291e41f4b71Sopenharmony_ci } 292e41f4b71Sopenharmony_ci } 293e41f4b71Sopenharmony_ci } 294e41f4b71Sopenharmony_ci} 295e41f4b71Sopenharmony_ci``` 296e41f4b71Sopenharmony_ci 297e41f4b71Sopenharmony_ci#### [Rule] Configure whether to load a driver as required based on service requirements. 298e41f4b71Sopenharmony_ci 299e41f4b71Sopenharmony_ci[Description] In the **device_info.hcs**, **preload** specifies the driver loading mode. The values and meanings of this field are as follows: 300e41f4b71Sopenharmony_ci 301e41f4b71Sopenharmony_ci```c 302e41f4b71Sopenharmony_citypedef enum { 303e41f4b71Sopenharmony_ci /* The driver is loaded by default during the system boot process. */ 304e41f4b71Sopenharmony_ci DEVICE_PRELOAD_ENABLE = 0, 305e41f4b71Sopenharmony_ci /* The driver is loaded after a quick start is complete if the system supports quick start. If the system does not support quick start, this value has the same meaning as DEVICE\_PRELOAD\_ENABLE. */ 306e41f4b71Sopenharmony_ci DEVICE_PRELOAD_ENABLE_STEP2, 307e41f4b71Sopenharmony_ci /* The driver is not 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. */ 308e41f4b71Sopenharmony_ci DEVICE_PRELOAD_DISABLE, 309e41f4b71Sopenharmony_ci /** Invalid value. */ 310e41f4b71Sopenharmony_ci DEVICE_PRELOAD_INVALID 311e41f4b71Sopenharmony_ci} DevicePreload; 312e41f4b71Sopenharmony_ci``` 313e41f4b71Sopenharmony_ci 314e41f4b71Sopenharmony_ciSet the **preload** field based on the service requirements. 315e41f4b71Sopenharmony_ci 316e41f4b71Sopenharmony_ci[Example] 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ci``` 319e41f4b71Sopenharmony_ciroot { 320e41f4b71Sopenharmony_ci device_info { 321e41f4b71Sopenharmony_ci sample_host { 322e41f4b71Sopenharmony_ci sample_device { 323e41f4b71Sopenharmony_ci device0 { 324e41f4b71Sopenharmony_ci preload = 2; // The driver is loaded as required. 325e41f4b71Sopenharmony_ci ... 326e41f4b71Sopenharmony_ci } 327e41f4b71Sopenharmony_ci } 328e41f4b71Sopenharmony_ci } 329e41f4b71Sopenharmony_ci } 330e41f4b71Sopenharmony_ci} 331e41f4b71Sopenharmony_ci``` 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci#### [Rec] When the preload field is set to 0, configure the loading priority based on the service requirements. 334e41f4b71Sopenharmony_ci 335e41f4b71Sopenharmony_ci[Description] In the **device_info.hcs** file, the **priority** field indicates the host and driver loading priority. The value of this field is an integer ranging from 0 to 200. For drivers in different hosts, a smaller priority value of the host indicates a higher driver loading priority. For drivers in the same host, a smaller priority value of the driver indicates a higher driver loading priority. The default value of the **priority** field is 100. If this field is not set or set to the same value for different drivers, the driver loading sequence cannot be ensured. You should configure the **priority** field based on the service requirements to ensure the driver loading sequence. 336e41f4b71Sopenharmony_ci 337e41f4b71Sopenharmony_ci[Example] 338e41f4b71Sopenharmony_ci 339e41f4b71Sopenharmony_ci``` 340e41f4b71Sopenharmony_ciroot { 341e41f4b71Sopenharmony_ci device_info { 342e41f4b71Sopenharmony_ci sample_host0 { 343e41f4b71Sopenharmony_ci priority = 100; 344e41f4b71Sopenharmony_ci sample_device { 345e41f4b71Sopenharmony_ci device0 { 346e41f4b71Sopenharmony_ci preload = 0; // The driver is loaded by default. 347e41f4b71Sopenharmony_ci priority = 100; // The HDF ensures that the driver is loaded before device1. 348e41f4b71Sopenharmony_ci ... 349e41f4b71Sopenharmony_ci } 350e41f4b71Sopenharmony_ci device1 { 351e41f4b71Sopenharmony_ci preload = 0; // The driver is loaded by default. 352e41f4b71Sopenharmony_ci priority = 200; // The HDF ensures that the driver is loaded after device0. 353e41f4b71Sopenharmony_ci ... 354e41f4b71Sopenharmony_ci } 355e41f4b71Sopenharmony_ci } 356e41f4b71Sopenharmony_ci } 357e41f4b71Sopenharmony_ci sample_host1 { 358e41f4b71Sopenharmony_ci priority = 100; // The HDF does not ensure the loading sequence because this host has the same priority as sample_host0. 359e41f4b71Sopenharmony_ci ... 360e41f4b71Sopenharmony_ci } 361e41f4b71Sopenharmony_ci } 362e41f4b71Sopenharmony_ci} 363e41f4b71Sopenharmony_ci``` 364e41f4b71Sopenharmony_ci 365e41f4b71Sopenharmony_ci**Private Configuration Information of the Driver** 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ciIf a driver has private configurations, you can add a driver configuration file to fill in default configurations of the driver. When loading the driver, the HDF obtains the configuration information, saves it in the **property** field of **HdfDeviceObject**, and passes it to the driver through **Bind** and **Init**. 368e41f4b71Sopenharmony_ci 369e41f4b71Sopenharmony_ci#### [Rule] Store the private configuration files of the drivers in different directories according to the component type or module. 370e41f4b71Sopenharmony_ci 371e41f4b71Sopenharmony_ci[Description] You must properly plan the directory for storing private configuration files of drivers. Do not store them in the root directory. 372e41f4b71Sopenharmony_ci 373e41f4b71Sopenharmony_ci[Example] 374e41f4b71Sopenharmony_ci 375e41f4b71Sopenharmony_ci```bash 376e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/sample/sample_config.hcs # Correct. The private configuration file is stored in the sample directory. 377e41f4b71Sopenharmony_ci 378e41f4b71Sopenharmony_ci$openharmony_src_root/vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/sample_config.hcs # Incorrect. The private configuration file is placed in the root directory. 379e41f4b71Sopenharmony_ci``` 380e41f4b71Sopenharmony_ci 381e41f4b71Sopenharmony_ci#### [Rule] Add the private configuration file of a driver to the hdf.hcs file in the hdf_config directory. 382e41f4b71Sopenharmony_ci 383e41f4b71Sopenharmony_ci[Description] The **hdf.hcs** file summarizes the configuration information. The HDF parses the file content and loads the private configuration information of the driver to the device node during the build and runtime. Include the private configuration file of the driver in the **hdf.hcs** file to trigger driver initialization. 384e41f4b71Sopenharmony_ci 385e41f4b71Sopenharmony_ci[Example] 386e41f4b71Sopenharmony_ci 387e41f4b71Sopenharmony_ci```c 388e41f4b71Sopenharmony_ci#include "device_info/device_info.hcs" 389e41f4b71Sopenharmony_ci#include "sample/sample_config.hcs" // The file contains the private configuration file of a driver. 390e41f4b71Sopenharmony_ci 391e41f4b71Sopenharmony_ciroot { 392e41f4b71Sopenharmony_ci module = "hisilicon,hi35xx_chip"; 393e41f4b71Sopenharmony_ci} 394e41f4b71Sopenharmony_ci``` 395e41f4b71Sopenharmony_ci 396e41f4b71Sopenharmony_ci#### [Rule] The value of the matchAttr field in the private configuration file of the driver must be the same as that of the deviceMatchAttr field in device_info.hcs. 397e41f4b71Sopenharmony_ci 398e41f4b71Sopenharmony_ci[Description] The HDF associates with the driver device through the **match_attr** field. A mismatch causes a failure to obtain the private configuration information. 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci[Example] 401e41f4b71Sopenharmony_ci 402e41f4b71Sopenharmony_ci``` 403e41f4b71Sopenharmony_ciroot { 404e41f4b71Sopenharmony_ci sample_config { 405e41f4b71Sopenharmony_ci ... 406e41f4b71Sopenharmony_ci match_attr = "sample_config"; // The value of this field must be the same as that of deviceMatchAttr in device_info.hcs. 407e41f4b71Sopenharmony_ci } 408e41f4b71Sopenharmony_ci} 409e41f4b71Sopenharmony_ci``` 410e41f4b71Sopenharmony_ci 411e41f4b71Sopenharmony_ci#### [Rule] Use underscores (_) in field names in the private configuration file. 412e41f4b71Sopenharmony_ci 413e41f4b71Sopenharmony_ci[Description] According to the naming rules in the C/C++ coding guide, use underscores (_) in field names in the private configuration file of a driver. In this way, the naming rule is satisfied during the definition of the private configuration data structure in the implementation code. It also makes unified management of the code and configuration files easier. 414e41f4b71Sopenharmony_ci 415e41f4b71Sopenharmony_ci[Example] 416e41f4b71Sopenharmony_ci 417e41f4b71Sopenharmony_ci``` 418e41f4b71Sopenharmony_ciroot { 419e41f4b71Sopenharmony_ci sample_config { 420e41f4b71Sopenharmony_ci sample_version = 1; // Use an underscore (_) in the field name. 421e41f4b71Sopenharmony_ci sample_bus = "I2C_0"; 422e41f4b71Sopenharmony_ci match_attr = "sample_config"; 423e41f4b71Sopenharmony_ci } 424e41f4b71Sopenharmony_ci} 425e41f4b71Sopenharmony_ci``` 426e41f4b71Sopenharmony_ci 427e41f4b71Sopenharmony_ci### HCS Macros 428e41f4b71Sopenharmony_ci 429e41f4b71Sopenharmony_ciThe private configuration information of a driver is loaded to **property** of **HdfDeviceObject**. This occupies memory space, which should be avoided for mini- and small-system devices. To minimize the memory usage, the HDF provides HCS macros to parse the private configuration information. 430e41f4b71Sopenharmony_ci 431e41f4b71Sopenharmony_ci#### [Rule] Use HCS macros to parse the private configuration information in memory-sensitive or cross-system scenario. 432e41f4b71Sopenharmony_ci 433e41f4b71Sopenharmony_ci[Description] You should specify the use cases of drivers. In memory-sensitive scenarios or if a driver needs to be used in mini-, small-, and standard-system devices, use HCS macros to parse the private configuration information for higher performance and portability. 434e41f4b71Sopenharmony_ci 435e41f4b71Sopenharmony_ci[Example] 436e41f4b71Sopenharmony_ci 437e41f4b71Sopenharmony_ci```c 438e41f4b71Sopenharmony_ci#include <utils/hcs_macro.h> 439e41f4b71Sopenharmony_ci 440e41f4b71Sopenharmony_ci#define SAMPLE_CONFIG_NODE HCS_NODE(HCS_ROOT, sample_config) 441e41f4b71Sopenharmony_ci 442e41f4b71Sopenharmony_ciASSERT_EQ(HCS_PROP(SAMPLE_CONFIG_NODE, sampleVersion), 1); 443e41f4b71Sopenharmony_ciASSERT_EQ(HCS_PROP(SAMPLE_CONFIG_NODE, sample_bus), "I2C_0"); 444e41f4b71Sopenharmony_ciASSERT_EQ(HCS_PROP(SAMPLE_CONFIG_NODE, match_attr), "sample_config"); 445e41f4b71Sopenharmony_ci``` 446e41f4b71Sopenharmony_ci 447e41f4b71Sopenharmony_ci### HDF Tools 448e41f4b71Sopenharmony_ci 449e41f4b71Sopenharmony_ci#### [Rule] Determine the communication scenario and HdfSbuf type. 450e41f4b71Sopenharmony_ci 451e41f4b71Sopenharmony_ci[Description] **HdfSbuf** is a data structure used for data transfer. This structure is classified into different types based on the communication scenario. These types are defined in the **hdf_sbuf.h** header file. 452e41f4b71Sopenharmony_ci 453e41f4b71Sopenharmony_ci```c 454e41f4b71Sopenharmony_cienum HdfSbufType { 455e41f4b71Sopenharmony_ci SBUF_RAW = 0, /* SBUF used for communication between the user space and the kernel space. */ 456e41f4b71Sopenharmony_ci SBUF_IPC, /* SBUF used for inter-process communication (IPC). */ 457e41f4b71Sopenharmony_ci SBUF_IPC_HW, /* Reserved for extension. */ 458e41f4b71Sopenharmony_ci SBUF_TYPE_MAX, /* Maximum value of the SBUF type. */ 459e41f4b71Sopenharmony_ci}; 460e41f4b71Sopenharmony_ci``` 461e41f4b71Sopenharmony_ci 462e41f4b71Sopenharmony_ciDetermine whether the data transfer is IPC in the user space or between the user space and kernel space, and then create the corresponding **HdfSbuf** structure. 463e41f4b71Sopenharmony_ci 464e41f4b71Sopenharmony_ci[Example] 465e41f4b71Sopenharmony_ci 466e41f4b71Sopenharmony_ci```c 467e41f4b71Sopenharmony_civoid SampleDispatchBetweenUserAndKernel() 468e41f4b71Sopenharmony_ci{ 469e41f4b71Sopenharmony_ci int32_t ret; 470e41f4b71Sopenharmony_ci /* Communication between the user space and kernel space. */ 471e41f4b71Sopenharmony_ci struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_RAW); 472e41f4b71Sopenharmony_ci ... 473e41f4b71Sopenharmony_ci ret = sample->dispatcher->Dispatch(&sample->object, CMD_SAMPLE_DISPATCH, data, NULL); 474e41f4b71Sopenharmony_ci ... 475e41f4b71Sopenharmony_ci HdfSBufRecycle(data); 476e41f4b71Sopenharmony_ci} 477e41f4b71Sopenharmony_ci``` 478e41f4b71Sopenharmony_ci 479e41f4b71Sopenharmony_ci[Example] 480e41f4b71Sopenharmony_ci 481e41f4b71Sopenharmony_ci```c++ 482e41f4b71Sopenharmony_civoid SampleDispatchIpc() 483e41f4b71Sopenharmony_ci{ 484e41f4b71Sopenharmony_ci /* IPC */ 485e41f4b71Sopenharmony_ci struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC); 486e41f4b71Sopenharmony_ci ... 487e41f4b71Sopenharmony_ci int ret = sample->dispatcher->Dispatch(sample, CMD_SAMPLE_DISPATCH, data, nullptr); 488e41f4b71Sopenharmony_ci ... 489e41f4b71Sopenharmony_ci HdfSBufRecycle(data); 490e41f4b71Sopenharmony_ci} 491e41f4b71Sopenharmony_ci``` 492e41f4b71Sopenharmony_ci 493e41f4b71Sopenharmony_ci#### [Rule] Define the HDF_LOG_TAG macro when using HDF logging. 494e41f4b71Sopenharmony_ci 495e41f4b71Sopenharmony_ci[Description] The HDF provides the **hdf_log.h** tool ,using which you can output driver run logs. The **HDF_LOG_TAG** macro specifies the log tag. You must define this macro before printing logs. 496e41f4b71Sopenharmony_ci 497e41f4b71Sopenharmony_ci[Example] 498e41f4b71Sopenharmony_ci 499e41f4b71Sopenharmony_ci```c 500e41f4b71Sopenharmony_ci#include <hdf_log.h> 501e41f4b71Sopenharmony_ci 502e41f4b71Sopenharmony_ci#define HDF_LOG_TAG sample_driver // Define the log tag. 503e41f4b71Sopenharmony_ci 504e41f4b71Sopenharmony_ciint32_t SampleDriverInit(struct HdfDeviceObject *deviceObject) 505e41f4b71Sopenharmony_ci{ 506e41f4b71Sopenharmony_ci HDF_LOGI("sample driver is initialized"); // Use the tool to print logs. 507e41f4b71Sopenharmony_ci return HDF_SUCCESS; 508e41f4b71Sopenharmony_ci} 509e41f4b71Sopenharmony_ci``` 510e41f4b71Sopenharmony_ci 511e41f4b71Sopenharmony_ci#### [Rule] Verify the return values of the HDF methods and use the error codes provided by the HDF. 512e41f4b71Sopenharmony_ci 513e41f4b71Sopenharmony_ci[Description] The HDF methods have specific return values. You should verify them rather than ignoring them. The return values correspond to error codes in the **hdf_base.h** header file. Use the error codes provided by the HDF when using the HDF or implementing custom methods. 514e41f4b71Sopenharmony_ci 515e41f4b71Sopenharmony_ci[Example] 516e41f4b71Sopenharmony_ci 517e41f4b71Sopenharmony_ci```c 518e41f4b71Sopenharmony_ciint32_t SampleDriverInit(struct HdfDeviceObject *deviceObject) 519e41f4b71Sopenharmony_ci{ 520e41f4b71Sopenharmony_ci int32_t ret; 521e41f4b71Sopenharmony_ci // Check whether the device type is successfully set. 522e41f4b71Sopenharmony_ci if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_DISPLAY)) { 523e41f4b71Sopenharmony_ci HDF_LOGE("HdfDeviceSetClass failed"); 524e41f4b71Sopenharmony_ci return HDF_FAILURE; 525e41f4b71Sopenharmony_ci } 526e41f4b71Sopenharmony_ci ret = InitDiver(); 527e41f4b71Sopenharmony_ci // A custom method uses an error code provided by the HDF. 528e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 529e41f4b71Sopenharmony_ci HDF_LOGE("init driver is failed"); 530e41f4b71Sopenharmony_ci return ret; 531e41f4b71Sopenharmony_ci } 532e41f4b71Sopenharmony_ci return HDF_SUCCESS; 533e41f4b71Sopenharmony_ci} 534e41f4b71Sopenharmony_ci``` 535e41f4b71Sopenharmony_ci 536e41f4b71Sopenharmony_ci### OSAL 537e41f4b71Sopenharmony_ci 538e41f4b71Sopenharmony_ciThe HDF OSAL shields the interface differences between OpenHarmony subsystems and provides unified OS interfaces, including memory management, threads, mutexes, spin locks, semaphores, timers, files, IRQ, time, atoms, firmware, and I/O operation modules. 539e41f4b71Sopenharmony_ci 540e41f4b71Sopenharmony_ci#### [Rule] Use OS interfaces through the OSAL for drivers used across mini-, small-, and standard-system devices. 541e41f4b71Sopenharmony_ci 542e41f4b71Sopenharmony_ci[Description] The OSAL shields the differences between OS interfaces. You should operate these OS interfaces based on the OSAL to ensure that drivers can run on different types of systems. 543e41f4b71Sopenharmony_ci 544e41f4b71Sopenharmony_ci[Example] 545e41f4b71Sopenharmony_ci 546e41f4b71Sopenharmony_ci```c 547e41f4b71Sopenharmony_ci#include <osal/osal_mem.h> 548e41f4b71Sopenharmony_ci#include <util/hdf_log.h> 549e41f4b71Sopenharmony_ci 550e41f4b71Sopenharmony_cistruct DevHandle *SampleInit(void) 551e41f4b71Sopenharmony_ci{ 552e41f4b71Sopenharmony_ci struct DevHandle *handle = (struct DevHandle *)OsalMemCalloc(sizeof(struct DevHandle)); 553e41f4b71Sopenharmony_ci if (handle == NULL) { 554e41f4b71Sopenharmony_ci HDF_LOGE("OsalMemCalloc handle failed"); 555e41f4b71Sopenharmony_ci return NULL; 556e41f4b71Sopenharmony_ci } 557e41f4b71Sopenharmony_ci return handle; 558e41f4b71Sopenharmony_ci} 559e41f4b71Sopenharmony_ci``` 560e41f4b71Sopenharmony_ci 561e41f4b71Sopenharmony_ci[Example] 562e41f4b71Sopenharmony_ci 563e41f4b71Sopenharmony_ci```c 564e41f4b71Sopenharmony_ci#include <osal/osal_time.h> 565e41f4b71Sopenharmony_ci 566e41f4b71Sopenharmony_civoid SampleSleep(uint32_t timeMs) 567e41f4b71Sopenharmony_ci{ 568e41f4b71Sopenharmony_ci OsalMSleep(timeMs); 569e41f4b71Sopenharmony_ci} 570e41f4b71Sopenharmony_ci``` 571e41f4b71Sopenharmony_ci 572e41f4b71Sopenharmony_ci### PAL 573e41f4b71Sopenharmony_ci 574e41f4b71Sopenharmony_ciThe HDF PAL abstracts platform drivers and provides unified operation interfaces for modules such as the GPIO, I2C, SPI, UART, RTC, SDIO, eMMC, DSI, PWM, and watchdog. 575e41f4b71Sopenharmony_ci 576e41f4b71Sopenharmony_ci#### [Rule] Use platform drivers across mini, small, and standard systems through the PAL. 577e41f4b71Sopenharmony_ci 578e41f4b71Sopenharmony_ci[Description] The PAL masks the differences between platform driver interfaces of different system types. You should operate these interfaces based on PAL to ensure that drivers can run on different types of systems. 579e41f4b71Sopenharmony_ci 580e41f4b71Sopenharmony_ci[Example] 581e41f4b71Sopenharmony_ci 582e41f4b71Sopenharmony_ci```c 583e41f4b71Sopenharmony_ci#include <platform/gpio_if.h> 584e41f4b71Sopenharmony_ci#include <util/hdf_log.h> 585e41f4b71Sopenharmony_ci#include <osal/osal_irq.h> 586e41f4b71Sopenharmony_ci#include <osal/osal_time.h> 587e41f4b71Sopenharmony_ci 588e41f4b71Sopenharmony_cistatic uint32_t g_irqCnt; 589e41f4b71Sopenharmony_ci 590e41f4b71Sopenharmony_ci/* Sample function of the GPIO IRQ service */ 591e41f4b71Sopenharmony_cistatic int32_t SampleGpioIrqHandler(uint16_t gpio, void *data) 592e41f4b71Sopenharmony_ci{ 593e41f4b71Sopenharmony_ci HDF_LOGE("%s: irq triggered, on gpio:%u, data=%p", __func__, gpio, data); 594e41f4b71Sopenharmony_ci g_irqCnt++; /* If the IRQ function is triggered, the number of global counters is incremented by 1. */ 595e41f4b71Sopenharmony_ci return GpioDisableIrq(gpio); 596e41f4b71Sopenharmony_ci} 597e41f4b71Sopenharmony_ci 598e41f4b71Sopenharmony_ci/* GPIO sample function */ 599e41f4b71Sopenharmony_cistatic int32_t SampleGpioIrqEdge(void) 600e41f4b71Sopenharmony_ci{ 601e41f4b71Sopenharmony_ci int32_t ret; 602e41f4b71Sopenharmony_ci uint16_t valRead; 603e41f4b71Sopenharmony_ci uint16_t mode; 604e41f4b71Sopenharmony_ci uint16_t gpio = 83; // Number of the GPIO pin to test 605e41f4b71Sopenharmony_ci uint32_t timeout; 606e41f4b71Sopenharmony_ci 607e41f4b71Sopenharmony_ci /* Set the output direction for the pin. */ 608e41f4b71Sopenharmony_ci ret = GpioSetDir(gpio, GPIO_DIR_OUT); 609e41f4b71Sopenharmony_ci ... 610e41f4b71Sopenharmony_ci /* Disable the IRP of this pin. */ 611e41f4b71Sopenharmony_ci ret = GpioDisableIrq(gpio); 612e41f4b71Sopenharmony_ci ... 613e41f4b71Sopenharmony_ci /* Set the IRR function for the pin. The trigger mode is both rising edge and falling edge. */ 614e41f4b71Sopenharmony_ci mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; 615e41f4b71Sopenharmony_ci ret = GpioSetIrq(gpio, mode, SampleGpioIrqHandler, NULL); 616e41f4b71Sopenharmony_ci ... 617e41f4b71Sopenharmony_ci /* Enable the IRQ for this pin. */ 618e41f4b71Sopenharmony_ci ret = GpioEnableIrq(gpio); 619e41f4b71Sopenharmony_ci ... 620e41f4b71Sopenharmony_ci g_irqCnt = 0; /* Reset the global counter. */ 621e41f4b71Sopenharmony_ci timeout = 0; /* Reset the waiting time. */ 622e41f4b71Sopenharmony_ci /* Wait for the IRQ function of this pin to trigger. The timeout duration is 1000 ms. */ 623e41f4b71Sopenharmony_ci while (g_irqCnt <= 0 && timeout < 1000) { 624e41f4b71Sopenharmony_ci ret = GpioRead(gpio, &valRead); 625e41f4b71Sopenharmony_ci ... 626e41f4b71Sopenharmony_ci ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); 627e41f4b71Sopenharmony_ci ... 628e41f4b71Sopenharmony_ci OsalMDelay(200); // Wait for an interrupt to be triggered. 629e41f4b71Sopenharmony_ci timeout += 200; 630e41f4b71Sopenharmony_ci } 631e41f4b71Sopenharmony_ci ret = GpioUnSetIrq(gpio); 632e41f4b71Sopenharmony_ci ... 633e41f4b71Sopenharmony_ci return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; 634e41f4b71Sopenharmony_ci} 635e41f4b71Sopenharmony_ci``` 636