OpenHarmony-3.HDF input子系统(5)
- HDF input 子系统
- OpenHarmony-4.0-Release
1.Input 概述
输入设备是用户与计算机系统进行人机交互的主要装置之一,是用户与计算机或者其他设备通信的桥梁。常见的输入设备有键盘、鼠标、游戏杆、触摸屏等。本文档将介绍基于 HDF_Input 模型的触摸屏器件 IC 为 GT911 驱动开发。
在HDF(Hardware Driver Foundation)驱动管理框架的基础上,Input驱动模型通过调用OSAL接口层和Platform接口层提供的基础接口进行开发,涉及的接口包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台的差异,所以基于Input驱动模型实现的Touchscreen驱动可以进行跨平台、跨OS迁移,从而实现驱动的一次开发、多端部署。
Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定Input相关配置、下载及更新固件等操作。
运作机制:
Input驱动模型基于HDF驱动框架、Platform接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Device Interface)层,通过Input-HDI层对外提供硬件能力,即上层Input Service可以通过HDI接口层获取相应的驱动能力,进而操控Touchscreen等输入设备。基于HDF驱动框架的Input驱动模型如下图所示:
Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者对器件驱动的开发效率。如下为模型各部分的说明:
- Input设备管理:为各类输入设备驱动提供Input设备的注册、注销接口,同时对Input设备列表进行统一管理。
- Input平台驱动:指各类Input设备的公共抽象驱动(例如触摸屏的公共驱动),该部分主要负责对板级硬件进行初始化、硬件中断处理、向manager注册Input设备等。
- Input器件驱动:指各器件厂家的差异化驱动,开发者可以通过适配平台驱动预留的差异化接口进行器件驱动开发,实现器件驱动开发量最小化。
- Input数据通道:提供一套通用的数据上报通道,各类别的Input设备驱动均可用此通道上报Input事件。
- Input配置解析:负责对Input设备的板级配置及器件私有配置进行解析及管理。
2.Touchscreen 设备
2.1.硬件接口
Touch 设备与主机通讯一般采用 I2C 总线完成数据的交互,为了提高触屏数据的实时性,触屏 IC 都会提供中断支持。当有触屏事件发生时,会触发主机中断管脚完成一次中断响应。中断处理函数中主机通过 I2C 总线读取触屏 IC 寄存器完成一次数据采集。
Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类:
-
电源接口
-
IO控制接口
-
通信接口
2.2.软件接口
Input HDF驱动提供给系统服务Input Service调用的HDI驱动能力接口,按照业务范围可以分为三大模块:
- Input设备管理模块
- Input数据上报模块
- Input业务控制模块
2.3.开发步骤
Input驱动模型的完整加载流程可以分为六步:
-
设备描述配置:由开发者参考已有模板进行设备描述配置,配置的信息包括驱动加载顺序、板级硬件信息、器件私有数据信息等。
-
加载Input设备管理驱动:由HDF驱动加载Input设备管理驱动,完成设备manager的创建并对其初始化。
-
加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。
-
加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。
-
器件设备向平台驱动注册:将实例化的器件设备注册到平台驱动,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。
-
Input设备注册:在器件初始化完成后,实例化Input设备,并将其注册到Input manager进行管理。
根据Input驱动模型的加载流程可知,Touchscreen器件驱动的开发过程主要包含以下三个步骤:
-
设备描述配置:目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。
-
板级配置及Touchscreen器件私有配置:配置对应的IO管脚功能,例如对单板上为Touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。
-
实现器件差异化适配接口:根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作。
3.HDF Input 框架
以RK3568为例,Touchscreen驱动主要相关代码:
- drivers/hdf_core/framework/model/input/driver/touchscreen/
- vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs
- vendor/hihope/rk3568/hdf_config/khdf/input/input_config.hcs
主要代码框架:
3.1.Input 内核配置
- KConfig\Makefile
drivers_hdf_core\adapter\khdf\linux\model\input\Kconfig:
config DRIVERS_HDF_INPUT
bool "Enable HDF input driver"
default n
depends on DRIVERS_HDF
help
Answer Y to enable HDF input driver.
config DRIVERS_HDF_TP_5P5_GT911
bool "Enable HDF tp 5P5 GT911 driver"
default n
depends on DRIVERS_HDF_INPUT
help
Answer Y to enable HDF TP 5P5 GT911 driver.
...
drivers_hdf_core\adapter\khdf\linux\model\input\Makefile:
INPUT_ROOT_DIR = ../../../../../framework/model/input/driver
obj-$(CONFIG_DRIVERS_HDF_INPUT) += \
$(INPUT_ROOT_DIR)/input_bus_ops/input_i2c_ops.o \
$(INPUT_ROOT_DIR)/hdf_input_device_manager.o \
$(INPUT_ROOT_DIR)/input_config_parser.o \
$(INPUT_ROOT_DIR)/event_hub.o \
$(INPUT_ROOT_DIR)/hdf_touch.o \
$(INPUT_ROOT_DIR)/hdf_key.o \
$(INPUT_ROOT_DIR)/hdf_hid_adapter.o
obj-$(CONFIG_DRIVERS_HDF_TP_5P5_GT911) += \
$(INPUT_ROOT_DIR)/touchscreen/touch_gt911.o
obj-$(CONFIG_ARCH_NXP_TOUCH) += \
$(INPUT_ROOT_DIR)/touchscreen/touch_ft5x06.o
obj-$(CONFIG_DRIVERS_HDF_TP_2P35_FT6236) += \
$(INPUT_ROOT_DIR)/touchscreen/touch_ft6336.o
obj-$(CONFIG_DRIVERS_HDF_INPUT_INFRARED) += \
$(INPUT_ROOT_DIR)/hdf_infrared.o
obj-$(CONFIG_DRIVERS_HDF_TP_5P43_FT5406) += \
$(INPUT_ROOT_DIR)/touchscreen/touch_ft5406.o
3.2.Input 设备配置
3.2.1.设备描述配置 (vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs)
input :: host {
hostName = "input_host";
priority = 100;
device_input_manager :: device { //管理层驱动HDF_INPUT_MANAGER
device0 :: deviceNode {
policy = 2; // 向外发布服务
priority = 100; // 加载优先级,在input模块内,manager模块优先级应为最高
preload = 0; // 加载该驱动,0:加载;1:不加载
permission = 0660;
moduleName = "HDF_INPUT_MANAGER";
serviceName = "hdf_input_host";
deviceMatchAttr = "";
}
}
device_hdf_touch :: device { // 公共驱动HDF_TOUCH
device0 :: deviceNode {
policy = 2;
priority = 120;
preload = 0;
permission = 0660;
moduleName = "HDF_TOUCH";
serviceName = "hdf_input_event1";
deviceMatchAttr = "touch_device1";
}
}
//适配gt911_5p5触摸屏驱动描述信息
device_touch_chip :: device {//设备节点
device0 :: deviceNode {//驱动的DeviceNode节点。
policy = 0;//驱动服务发布的策略
priority = 130;//驱动启动优先级(0-200),值越大优先级越低,
preload = 0;//驱动按需加载字段,0:默认加载,1:当系统支持快速启动的时候,则在系统完成之后再加载这一类驱动 2:默认不加载,支持后续动态加载
permission = 0660;//驱动创建设备节点权限
moduleName = "HDF_TOUCH_GT911";//驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
serviceName = "hdf_touch_gt911_service";//驱动对外发布服务的名称,必须唯一
deviceMatchAttr = "zsj_gt911_5p5";//驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等。
}
}
...
}
从上面可以看出,与触摸相关的主要是3个节点,刚好与实现TS驱动模型对应:
- HDF_INPUT_MANAGER:Input设备管理
- HDF_TOUCH:触摸屏的公共抽象驱动
- HDF_TOUCH_GT911:具体的Input器件驱动
3.2.2.板级配置及器件私有配置(vendor/hihope/rk3568/hdf_config/khdf/input/input_config.hcs)
如果驱动配置有deviceMatchAttr参数,需添加一个私有配置文件,根据具体需求增删及修改如下配置文件信息。
root {
input_config {
touchConfig {
touch0 {
//公共驱动HDF_TOUCH 私有配置信息
boardConfig {
match_attr = "touch_device1";
inputAttr {
/* 0:touch 1:key 2:keyboard 3:mouse 4:button 5:crown 6:encoder */
inputType = 0;
solutionX = 720;
solutionY = 1280;
devName = "main_touch";
}
// Hi3516DV300-Runhe gt911--5p5 & 4p0
busConfig {
// 0:i2c 1:spi
busType = 0;
busNum = 1;
clkGpio = 86;
dataGpio = 87;
i2cClkIomux = [0x114f0048, 0x403]; // i2c_clk对应pin的寄存器配置
i2cDataIomux = [0x114f004c, 0x403]; // i2c_data对应pin的寄存器配置
}
pinConfig {
rstGpio = 14;
intGpio = 13;
rstRegCfg = [0x112f0094, 0x400]; // reset对应pin的寄存器配置
intRegCfg = [0x112f0098, 0x400]; // interrupt对应pin的寄存器配置
}
powerConfig {
/* 0:unused 1:ldo 2:gpio 3:pmic */
vccType = 2;
vccNum = 20; // gpio20
vccValue = 1800;
vciType = 1;
vciNum = 12; // ldo12
vciValue = 3300;
}
featureConfig {
capacitanceTest = 0;
gestureMode = 0;
gloverMOde = 0;
coverMode = 0;
chargerMode = 0;
knuckleMode = 0;
}
}
chipConfig {
//适配gt911 触摸屏私有驱动描述信息
template touchChip {
match_attr = "";
chipName = "gt911";
vendorName = "zsj";
chipInfo = "AAAA11222"; // 4-ProjectName, 2-TP IC, 3-TP Module
/* 0:i2c 1:spi*/
busType = 0;
deviceAddr = 0x5D;
/* 0:None 1:Rising 2:Failing 4:High-level 8:Low-level */
irqFlag = 2;
maxSpeed = 400;
chipVersion = 0; //parse Coord TypeA
powerSequence {
/* [type, status, dir , delay]
<type> 0:none 1:vcc-1.8v 2:vci-3.3v 3:reset 4:int
<status> 0:off or low 1:on or high 2:no ops
<dir> 0:input 1:output 2:no ops
<delay> meanings delay xms, 20: delay 20ms
*/
powerOnSeq = [4, 0, 1, 5,
3, 0, 1, 10,
3, 1, 1, 60,
4, 2, 0, 50];
suspendSeq = [3, 0, 2, 10];
resumeSeq = [3, 1, 2, 10];
powerOffSeq = [3, 0, 2, 10,
1, 0, 2, 20];
}
}
chip0 :: touchChip {
match_attr = "zsj_gt911_5p5";
chipInfo = "ZIDN45100"; // 4-ProjectName, 2-TP IC, 3-TP Module
chipVersion = 0; //parse point by TypeA
}
chip1 :: touchChip {
match_attr = "zsj_gt911_4p0";
chipInfo = "ZIDN45101";
chipVersion = 1; //parse point by TypeB
}
}
}
}
}
}
device_info中的节点通过 deviceMatchAttr和 match_attr字段匹配配置,chipConfig配置中主要定义了一些与实际硬件相关的信息:
- 硬件接口的总线类型,主要有2类:SPI和I2C
- 设备地址,这里使用的是I2C接口,所以就是I2C从设备的地址
- 总线最高速率
- 中断触发方式:边缘触发(上升沿、下降沿),还是电平触发(高低电平)
- 电源相关的时序:上下电时序,休眠和唤醒时序
- 自定义的一些info,版本等
3.2.3.将配置文件添加到板级配置:
将上面两个配置文件添加到板级配置入口文件hdf.hcs中。
./vendor/hihope/rk3568/hdf_config/khdf/hdf.hcs
#include "input/input_config.hcs"
#include "device_info/device_info.hcs"
3.3.驱动实现
-
对于touch 类型的设备,公共驱动框架已实现。
- drivers_hdf_core\framework\model\input\driver\hdf_touch.c
-
适配gt911_5p5触摸屏需要完成器件层驱动初始化、释放资源、注册驱动至HDF框架及触摸屏器件差异化接口适配
-
drivers_hdf_core\framework\model\input\driver\touchscreen\touch_gt911.c
3.3.1.GT911器件驱动
1).注册到HDF框架:(注意:g_touchGoodixChipEntry没有实现Bind接口)
drivers_hdf_core\framework\model\input\driver\touchscreen\touch_gt911.c:
//驱动注册到HDF框架函数
struct HdfDriverEntry g_touchGoodixChipEntry = {
.moduleVersion = 1,
.moduleName = "HDF_TOUCH_GT911", //驱动名称,该字段的值必须和驱动信息配置文件中moduleName的值一致
.Init = HdfGoodixChipInit,
.Release = HdfGoodixChipRelease,
};
HDF_INIT(g_touchGoodixChipEntry);
2).器件层驱动初始化
//函数操作集,主要包括初始化,休眠唤醒,数据处理,固件更新,能力设置等接口
static struct TouchChipOps g_gt911ChipOps = {
.Init = ChipInit,
.Detect = ChipDetect,
.Resume = ChipResume,
.Suspend = ChipSuspend,
.DataHandle = ChipDataHandle,
.UpdateFirmware = UpdateFirmware,
.SetAbility = SetAbility,
};
static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device)
{
TouchChipCfg *chipCfg = NULL;
ChipDevice *chipDev = NULL;
//器件配置结构体内存申请、配置信息解析及挂载
chipCfg = ChipConfigInstance(device);
//器件实例化
chipDev = ChipDeviceInstance();
chipDev->chipCfg = chipCfg;
chipDev->ops = &g_gt911ChipOps; //回调函数
chipDev->chipName = chipCfg->chipName;
chipDev->vendorName = chipCfg->vendorName;
device->priv = (void *)chipDev;
//注册器件驱动至平台驱动
if (RegisterTouchChipDevice(chipDev) != HDF_SUCCESS) {
goto EXIT1;
}
HDF_LOGI("%s: exit succ, chipName = %s", __func__, chipCfg->chipName);
return HDF_SUCCESS;
}
RegisterTouchChipDevice()函数主要负责:
- DeviceBindDriver:绑定设备与驱动,从而通过InputDeviceInstance函数创建inputDev。
- ChipDriverInit :主要是上电操作,Detect设备,UpdateFirmware,配置使能中断,设置中断处理函数(坐标上报等就在里面)等操作。
- RegisterInputDevice:将InputDev设备注册至input驱动管理层 (hdf_input_device_manager.c)。
- chipDev->ops->SetAbility:调用chipdev的SetAbility接口。
3).器件层驱动数据上报
正常流程需要实现HdfGoodixChipBind 函数用于触摸屏和外部进行数据通信,但是公共驱动层HDF_TOUCH已经用HdfTouchDriverBind函数实现,器件不用重新实现,可以直接使用。
3.3.2. HDF Input 公共驱动层HDF_TOUCH
- 初始化及注册驱动至HDF框架
drivers_hdf_core\framework\model\input\driver\hdf_touch.c
struct HdfDriverEntry g_hdfTouchEntry = {
.moduleVersion = 1,
.moduleName = "HDF_TOUCH",
.Bind = HdfTouchDriverBind, //驱动对外提供的服务能力,将相关的务接口绑定到HDF框架
.Init = HdfTouchDriverProbe,
.Release = HdfTouchDriverRelease,
};
HDF_INIT(g_hdfTouchEntry);
- HdfTouchDriverBind
通过Bind对外提供IoService接口(Dispatch),主要有以下接口:
static int32_t HdfTouchDriverBind(struct HdfDeviceObject *device)
{
static struct IDeviceIoService touchService = {
.Dispatch = HdfTouchDispatch,
};
device->service = &touchService;
return HDF_SUCCESS;
}
static int32_t HdfTouchDispatch(struct HdfDeviceIoClient *client, int32_t cmd,
struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t ret;
TouchDriver *touchDriver = NULL;
...
switch (cmd) {
case GET_DEV_TYPE:
ret = TouchGetDevType(touchDriver, reply);
break;
case SET_PWR_STATUS:
ret = TouchSetPowerStatus(touchDriver, data);
break;
case GET_PWR_STATUS:
ret = TouchGetPowerStatus(touchDriver, reply);
break;
...
default:
ret = HDF_SUCCESS;
HDF_LOGE("%s: cmd unknown, cmd = 0x%x", __func__, cmd);
break;
}
return ret;
}
- HdfTouchDriverProbe
static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device)
{
int32_t ret;
TouchBoardCfg *boardCfg = NULL;
TouchDriver *touchDriver = NULL;
/* 板级信息结构体内存申请及hcs配置信息解析 */
boardCfg = BoardConfigInstance(device);
/* 公共驱动结构体内存申请 */
touchDriver = TouchDriverInstance();
// 初始化驱动数据,Setup bus接口(这里主要是i2c)
ret = TouchDriverInit(touchDriver, boardCfg);
if (ret == HDF_SUCCESS) {
touchDriver->hdfTouchDev = device;
touchDriver->boardCfg = boardCfg;
/* 添加驱动至公共驱动层驱动管理链表,当设备与驱动进行绑定时使用该链表进行查询 */
AddTouchDriver(touchDriver);
device->priv = (void *)touchDriver;
//对于RK平台,这里会注册一个PM的监听器,用来处理休眠和唤醒
#if defined(CONFIG_ARCH_ROCKCHIP)
HdfTouchDriverRegisterPowerListener(device);
#endif
return HDF_SUCCESS;
}
}
static TouchDriver *g_touchDriverList[MAX_TOUCH_DEVICE];
static void AddTouchDriver(TouchDriver *driver)
{
int32_t i;
for (i = 0; i < MAX_TOUCH_DEVICE; i++) {
if (g_touchDriverList[i] == NULL) {
g_touchDriverList[i] = driver;
return;
}
}
}
3.3.3. HDF Input 管理驱动层HDF_INPUT_MANAGER
- 初始化及注册驱动至HDF框架
drivers_hdf_core\framework\model\input\driver\hdf_input_device_manager.c
struct HdfDriverEntry g_hdfInputEntry = {
.moduleVersion = 1,
.moduleName = "HDF_INPUT_MANAGER",
.Bind = HdfInputManagerBind,
.Init = HdfInputManagerInit,
.Release = HdfInputManagerRelease,
};
HDF_INIT(g_hdfInputEntry);
- RegisterInputDevice
int32_t RegisterInputDevice(InputDevice *inputDev)
{
int32_t ret;
/* 申请ID,该ID对于不同input设备唯一 */
ret = AllocDeviceID(inputDev);
/* 该函数包含了对hid类设备的特殊处理,对于触摸屏驱动,该函数无实质操作; */
ret = CreateDeviceNode(inputDev);
/* 内核态数据传送至用户态需使用IOService能力,需要申请buffer */
ret = AllocPackageBuffer(inputDev);
#ifndef __LITEOS_M__
ret = InitEventWorkQueue(inputDev);
if (ret != HDF_SUCCESS) {
goto EXIT1;
}
#endif // __LITEOS_M__
/* 将input设备添加进设备全局管理链表 */
AddInputDevice(inputDev);
return ret;
}
refer to
- https://zhuanlan.zhihu.com/p/673299244
- https://ost.51cto.com/posts/8176
- https://laval.csdn.net/65b796d92c13685765def369.html
- https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-peripherals-touch-des.md
原文地址:https://blog.csdn.net/weixin_41028621/article/details/144399269
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!