Drivers in OpenHarmony are categorized into platform drivers and device drivers. Platform drivers handle on-SoC peripherals such as GPIO, I2C, and SPI controllers. Device drivers manage external components like LCD displays, touch panels, and WLAN modules connected to the SoC.
The HDF (Hardware Driver Foundation) framework enables cross-operating system driver compatibility. When developing HDF drivers, using only HDF-provided interfaces ensures the driver maintains portability across different systems. Platform driver definitions can be found in the source directory //drivers/hdf_core/framework/support/platform/include.
Directory Structure
Platform drivers should be created under //device/vendor_name/soc_name/drivers. The recommended organization follows this hierarchy:
device/
├── vendor_name/
│ ├── drivers/
│ │ ├── common/
│ │ ├── Kconfig
│ │ └── lite.mk
│ ├── soc_name/
│ │ ├── drivers/
│ │ │ ├── dmac/
│ │ │ ├── gpio/
│ │ │ ├── i2c/
│ │ │ ├── mipi_dsi/
│ │ │ ├── mmc/
│ │ │ ├── pwm/
│ │ │ ├── rtc/
│ │ │ ├── spi/
│ │ │ ├── uart/
│ │ │ └── watchdog/
│ ├── board_name/Porting a platform driver involves injecting an implementation instance into the HDF driver model. The following example demonstrates GPIO driver porting.
Step 1: Implementing the GPIO Driver
Create a source file at //device/vendor_name/soc_name/drivers/gpio/soc_gpio_impl.c:
#include "gpio_core.h"
struct SocGpioController {
struct GpioCntlr base;
void *privateData;
};
static int32_t SocGpioBind(struct HdfDeviceObject *device)
{
(void)device;
return HDF_SUCCESS;
}
static int32_t SocGpioInit(struct HdfDeviceObject *device)
{
struct SocGpioController *ctrl = GpioControllerCreate();
if (ctrl == NULL) {
HDF_LOGE("%s: failed to create controller", __func__);
return HDF_FAILURE;
}
int32_t result = GpioCntlrAdd(&ctrl->base);
if (result != HDF_SUCCESS) {
HDF_LOGE("%s: registration failed: %d", __func__, result);
GpioControllerDestroy(ctrl);
return result;
}
device->priv = ctrl;
return HDF_SUCCESS;
}
static void SocGpioRelease(struct HdfDeviceObject *device)
{
struct GpioCntlr *cntlr = GpioCntlrFromDevice(device);
if (cntlr != NULL) {
GpioCntlrRemove(cntlr);
}
struct SocGpioController *ctrl = (struct SocGpioController *)device->priv;
if (ctrl != NULL) {
GpioControllerDestroy(ctrl);
}
}
struct HdfDriverEntry g_socGpioEntry = {
.moduleVersion = 1,
.Bind = SocGpioBind,
.Init = SocGpioInit,
.Release = SocGpioRelease,
.moduleName = "SOC_VENDOR_gpio",
};
HDF_INIT(g_socGpioEntry);Step 2: Vendor Build Entry
Configure the vendor-level build entry in device/vendor_name/drivers/lite.mk:
SOC_VENDOR := $(subst $",,$(LOSCFG_DEVICE_COMPANY))
SOC_CHIP := $(subst $",,$(LOSCFG_PLATFORM))
LIB_SUBDIRS += $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR)/$(SOC_CHIP)/drivers/Step 3: SoC Driver Build Entry
Create device/vendor_name/soc_name/drivers/lite.mk:
DRIVER_ROOT := $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR)/$(SOC_CHIP)/drivers/
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO), y)
LITEOS_BASELIB += -lhdf_gpio
LIB_SUBDIRS += $(DRIVER_ROOT)/gpio
endifStep 4: GPIO Module Build Configuration
Create the module build file in the gpio directory:
include $(LITEOSTOPDIR)/config.mk
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk
MODULE_NAME := hdf_gpio
LOCAL_CFLAGS += $(HDF_INCLUDE)
LOCAL_SRCS += soc_gpio_impl.c
LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char
include $(HDF_DRIVER)Step 5: Device Configuration
Register the driver in the product configuration file at //vendor/vendor_name/product_name/config/device_info/device_info.hcs. Platform drivers should be placed under the platform host:
root {
platform :: host {
device_gpio :: device {
device0 :: deviceNode {
policy = 0;
priority = 10;
permission = 0644;
moduleName = "SOC_VENDOR_gpio";
}
}
}
}The moduleName value must match the one defined in the driver entry structure.