> 文档中心 > OpenHarmony HDF驱动框架input模块介绍

OpenHarmony HDF驱动框架input模块介绍


一、Hdf Framework

HDF 驱动框架

OpenAtom OpenHarmony(以下简称“OpenHarmony”)系统 HDF 驱动框架采用 C 语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动一次开发,多系统部署的效果。 (引用原文)

OpenHarmony HDF驱动框架input模块介绍

代码目录

/drivers/framework├── ability #提供驱动开发的能力支持,如消息模型库等│   ├── config     #配置解析代码│   └── sbuf#数据序列化代码├── core    #实现驱动框架的核心代码│   ├── adapter    #实现对内核操作接口适配,提供抽象化的接口供开发者使用│   ├── common     #驱动框架公共基础代码│   ├── host#驱动宿主环境模块│   ├── manager    #驱动框架管理模块│   └── shared     #host和manager共享模块代码├── include #驱动框架对外提供能力的头文件│   ├── config     #提供配置解析能力的头文件│   ├── core#驱动框架对外提供的头文件│   ├── net #网络数据操作相关的头文件│   ├── osal#系统适配相关接口的头文件│   ├── platform   #平台设备相关接口的头文件│   ├── utils      #驱动框架公共能力的头文件│   └── wifi#WLAN对外提供能力的头文件├── model   #提供驱动通用框架模型│   ├── display    #显示框架模型│   ├── input      #输入框架模型│   ├── network    #WLAN框架模型│   └── sensor     #Sensor驱动模型├── support #提系统的基础能力 │   └── platform   #平台设备驱动框架及访问接口,范围包括GPIO、I2C、SPI等├── tools   #hdf框架工具相关的源码│   └── hc-gen     #配置管理工具源码└── utils   #提供基础数据结构和算法等

二、input 驱动模型

基于HDF驱动框架的Input驱动模型

OpenHarmony HDF驱动框架input模块介绍

Input驱动模型介绍

Input驱动模型核心部分由设备管理层公共驱动层器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明:

  • Input设备管理:为各类输入设备驱动提供Input设备的注册、注销接口,同时统一管理Input设备列表。
  • Input平台驱动:指各类Input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册Input设备等。
  • Input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化。
  • Input数据通道:提供一套通用的数据上报通道,各类别的Input设备驱动均可用此通道上报Input事件。
  • Input配置解析:负责对Input设备的板级配置及器件私有配置进行解析及管理。

Input模型工作流程解析

私有配置信息解析

./drivers/framework/model/input/driver/input_config_parser.c 

根据 OSAL 提供的配置解析函数,可以将 hcs 文件中各字段含义进行解析,具体请参考 input_config_parser.c 中各函数的实现。如果提供的模板不能满足需求,在 hcs 文件中添加相应信息后,需要根据添加的字段开发相应的解析函数。

static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode,    BoardAttrCfg *attr){    int32_t ret;    ret = parser->GetUint8(attrNode, "inputType", &attr->devType, 0);    CHECK_PARSER_RET(ret, "GetUint8");    ret = parser->GetString(attrNode, "devName", &attr->devName, NULL);    CHECK_PARSER_RET(ret, "GetString");    ret = parser->GetUint32(attrNode, "solutionX", &attr->resolutionX, 0);    CHECK_PARSER_RET(ret, "GetUint32");    ret = parser->GetUint32(attrNode, "solutionY", &attr->resolutionY, 0);    CHECK_PARSER_RET(ret, "GetUint32");    return HDF_SUCCESS;}

管理驱动层初始化及注册驱动至HDF框架

./drivers/framework/model/input/driver/hdf_input_device_manager.c 
static int32_t HdfInputManagerInit(struct HdfDeviceObject *device){    HDF_LOGI("%s: enter", __func__);    if (device == NULL) { HDF_LOGE("%s: device is null", __func__); return HDF_ERR_INVALID_PARAM;    }    /* 分配内存给manager,manager中将存放所有input设备 */     g_inputManager = InputManagerInstance();    if (g_inputManager == NULL) { return HDF_ERR_MALLOC_FAIL;    }    if (OsalMutexInit(&g_inputManager->mutex) != HDF_SUCCESS) { HDF_LOGE("%s: mutex init failed", __func__); OsalMemFree(g_inputManager); g_inputManager = NULL; return HDF_FAILURE;    }    g_inputManager->initialized = true;    g_inputManager->hdfDevObj = device;    HDF_LOGI("%s: exit succ", __func__);    return HDF_SUCCESS;}struct HdfDriverEntry g_hdfInputEntry = {     .moduleVersion = 1,     .moduleName = "HDF_INPUT_MANAGER",     .Bind = HdfInputManagerBind,     .Init = HdfInputManagerInit,     .Release = HdfInputManagerRelease, }; HDF_INIT(g_hdfInputEntry); //驱动注册入口

公共驱动层初始化及注册驱动至HDF框架

./drivers/framework/model/input/driver/hdf_touch.c 
static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device) {    ...     /* 板级信息结构体内存申请及hcs配置信息解析 */     boardCfg = BoardConfigInstance(device);     ...     /* 公共驱动结构体内存申请 */     touchDriver = TouchDriverInstance();     ...     /* 依据解析出的板级信息进行公共资源初始化,如IIC初始化 */     ret = TouchDriverInit(touchDriver, boardCfg);     if (ret == HDF_SUCCESS) {  ... /* 添加驱动至公共驱动层驱动管理链表,当设备与驱动进行绑定时使用该链表进行查询 */  AddTouchDriver(touchDriver);  ...     }     ... } struct HdfDriverEntry g_hdfTouchEntry = {     .moduleVersion = 1,     .moduleName = "HDF_TOUCH",     .Bind = HdfTouchDriverBind,     .Init = HdfTouchDriverProbe,     .Release = HdfTouchDriverRelease, };     HDF_INIT(g_hdfTouchEntry);//驱动注册入口 

器件驱动层初始化及注册驱动至HDF框架

具体请参考适配器件私有驱动器件层驱动初始化及注册驱动至 HDF 框架部分。

具体调用逻辑串联函数

Input 模型管理层驱动 init 函数初始化了设备管理链表**,公共驱动层**初始化函数完成了相关结构体的内存申请。器件驱动相关信息通过 RegisterChipDevice 函数对公共驱动层相关结构体进行信息填充,同时完成了相关硬件信息的初始化(如中断注册等),绑定设备与驱动组成 inputDev 通过 RegisterInputDevice 函数向驱动管理层进行注册,在 RegisterInputDevice 函数中主要实现了将 inputDev 向设备管理链表的添加等功能。如下所示为两个函数的实现部分:

./drivers/framework/model/input/driver/hdf_touch.c 
int32_t RegisterTouchChipDevice(ChipDevice *chipDev){    int32_t ret;    InputDevice *inputDev = NULL;    if ((chipDev == NULL) || (chipDev->chipCfg == NULL)) { return HDF_ERR_INVALID_PARAM;    }    /* 绑定设备与驱动,从而通过InputDeviceInstance函数创建inputDev */     ret = DeviceBindDriver(chipDev);    if (ret != HDF_SUCCESS) { HDF_LOGE("%s: chip device match driver failed", __func__); return HDF_FAILURE;    }    /* 主要包含器件中断注册及中断处理函数,处理函数中有数据上报用户态的数据通道 */    ret = ChipDriverInit(chipDev);    if (ret != HDF_SUCCESS) { goto EXIT;    }     /* 申请内存实例化InputDev */     inputDev = InputDeviceInstance(chipDev);    if (inputDev == NULL) { return HDF_ERR_MALLOC_FAIL;    }     /* 将InputDev设备注册至input驱动管理层 */     ret = RegisterInputDevice(inputDev);    if (ret != HDF_SUCCESS) { goto EXIT1;    }    chipDev->driver->inputDev = inputDev;    chipDev->ops->SetAbility(chipDev);    return HDF_SUCCESS;EXIT1:    OsalMemFree(inputDev);EXIT:    chipDev->driver->device = NULL;    return HDF_FAILURE;}
./drivers/framework/model/input/driver/hdf_input_device_manager.c 
int32_t RegisterInputDevice(InputDevice *inputDev){    int32_t ret;    HDF_LOGI("%s: enter", __func__);    if (inputDev == NULL) { HDF_LOGE("%s: inputdev is null", __func__); return HDF_ERR_INVALID_PARAM;    }    if ((g_inputManager == NULL) || (g_inputManager->initialized == false)) { HDF_LOGE("%s: dev manager is null or initialized failed", __func__); return HDF_FAILURE;    }    OsalMutexLock(&g_inputManager->mutex);    /* 申请ID,该ID对于不同input设备唯一 */     ret = AllocDeviceID(inputDev);    if (ret != HDF_SUCCESS) { goto EXIT;    }    /* 该函数包含了对hid类设备的特殊处理,对于触摸屏驱动,该函数无实质操作; */     ret = CreateDeviceNode(inputDev);    if (ret != HDF_SUCCESS) { goto EXIT1;    }    /* 内核态数据传送至用户态需使用IOService能力,需要申请buffer */    ret = AllocPackageBuffer(inputDev);    if (ret != HDF_SUCCESS) { goto EXIT1;    }    /* 将input设备添加进设备全局管理链表 */     AddInputDevice(inputDev);    OsalMutexUnlock(&g_inputManager->mutex);    HDF_LOGI("%s: exit succ, devCount is %d", __func__, g_inputManager->devCount);    return HDF_SUCCESS;EXIT1:    DeleteDeviceNode(inputDev);EXIT:    OsalMutexUnlock(&g_inputManager->mutex);    return ret;}

三、Input模块HDI接口层框架

Input模块HDI(Hardware Driver Interface)接口定义及其实现,对上层输入服务提供操作input设备的驱动能力接口,HDI接口主要包括如下三大类:

  • InputManager:管理输入设备,包括输入设备的打开、关闭、设备列表信息获取等;

  • InputReporter:负责输入事件的上报,包括注册、注销数据上报回调函数等;

  • InputController:提供input设备的业务控制接口,包括获取器件信息及设备类型、设置电源状态等

    OpenHarmony HDF驱动框架input模块介绍

目录

drivers_peripheral 仓下源代码目录结构如下所示

/drivers/peripheral/input├── hal  # input模块的hal层代码│   └── include# input模块hal层内部的头文件│   └── src    # input模块hal层代码的具体实现├── interfaces  # input模块对上层服务提供的驱动能力接口│   └── include# input模块对外提供的接口定义├── test # input模块的测试代码│   └── unittest      # input模块的单元测试代码

使用说明

**drivers_peripheral**仓核心功能是提供Input驱动能力接口供上层输入系统服务调用,提供的驱动能力接口统一归属为HDI接口层。

通过如下简要示例代码说明Input HDI接口的使用:

#include "input_manager.h"#define DEV_INDEX 1IInputInterface *g_inputInterface;InputReportEventCb g_callback;/* 定义数据上报的回调函数 */static void ReportEventPkgCallback(const EventPackage **pkgs, uint32_t count){    if (pkgs == NULL || count > MAX_PKG_NUM) { return;    }    for (uint32_t i = 0; i type, pkgs[i]->code, pkgs[i]->value);    }}int InputServiceSample(void){    uint32_t devType = INIT_DEFAULT_VALUE;    /* 获取Input驱动能力接口 */    int ret = GetInputInterface(&g_inputInterface);    if (ret != INPUT_SUCCESS) { HDF_LOGE("%s: get input interfaces failed, ret = %d", __func__, ret); return ret;    }    INPUT_CHECK_NULL_POINTER(g_inputInterface, INPUT_NULL_PTR);    INPUT_CHECK_NULL_POINTER(g_inputInterface->iInputManager, INPUT_NULL_PTR);    /* 打开特定的input设备 */    ret = g_inputInterface->iInputManager->OpenInputDevice(DEV_INDEX);    if (ret) { HDF_LOGE("%s: open input device failed, ret = %d", __func__, ret); return ret;    }    INPUT_CHECK_NULL_POINTER(g_inputInterface->iInputController, INPUT_NULL_PTR);    /* 获取对应input设备的类型 */    ret = g_inputInterface->iInputController->GetDeviceType(DEV_INDEX, &devType);    if (ret) { HDF_LOGE("%s: get device type failed, ret: %d", __FUNCTION__, ret); return ret;    }    HDF_LOGI("%s: device1's type is %u\n", __FUNCTION__, devType);    /* 给特定的input设备注册数据上报回调函数 */    g_callback.ReportEventPkgCallback = ReportEventPkgCallback;    INPUT_CHECK_NULL_POINTER(g_inputInterface->iInputReporter, INPUT_NULL_PTR);    ret  = g_inputInterface->iInputReporter->RegisterReportCallback(DEV_INDEX, &g_callback);    if (ret) { HDF_LOGE("%s: register callback failed, ret: %d", __FUNCTION__, ret);return ret;    }    HDF_LOGI("%s: wait 10s for testing, pls touch the panel now", __FUNCTION__);    OsalMSleep(KEEP_ALIVE_TIME_MS);    /* 注销特定input设备上的回调函数 */    ret  = g_inputInterface->iInputReporter->UnregisterReportCallback(DEV_INDEX);    if (ret) { HDF_LOGE("%s: unregister callback failed, ret: %d", __FUNCTION__, ret); return ret;    }    /* 关闭特定的input设备 */    ret = g_inputInterface->iInputManager->CloseInputDevice(DEV_INDEX);    if (ret) { HDF_LOGE("%s: close device failed, ret: %d", __FUNCTION__, ret);return ret;    }    return 0;}