OpenHarmony Input 驱动框架

系统教程10个月前发布
5 0 0

OpenHarmony Input 驱动框架

一、Hdf Framework

HDF 驱动框架

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

OpenHarmony 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 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 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 1
IInputInterface *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 < count; i++) {
HDF_LOGI("%s: pkgs[%d] = 0x%x, 0x%x, %d", __func__, i, pkgs[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;
}

​想了解更多内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://ost.51cto.com​

OpenHarmony Input 驱动框架

© 版权声明

相关文章