Touchscreen开发实例
基于HDF驱动模型,加载启动Touchscreen驱动,代码形式如下,具体原理可参考。
执行初始化
如下初始化流程包含常用的步骤,实际业务开发时,可根据具体需求增删及修改如下初始化中的相关步骤,具体示例如下。
{
(void)object;
/* 创建全局数据结构体,用于存储器件驱动相关信息 */
g_coreData = (TouchCoreData *)OsalMemAlloc(sizeof(TouchCoreData));
if (g_coreData == NULL) {
HDF_LOGE("%s: malloc failed", __func__);
return HDF_ERR_MALLOC_FAIL;
}
if (memset_s(g_coreData, sizeof(TouchCoreData), 0, sizeof(TouchCoreData)) != EOK) {
HDF_LOGE("%s: memset_s fail", __func__);
return;
}
/* 初始化全局数据结构体,将器件驱动相关的配置信息,进行解析赋值 */
TouchConfigInit(g_coreData);
/* 设置GPIO相关的属性及状态 */
if (TouchSetupGpio(g_coreData)) {
goto ERR_EXIT;
}
/* 设置并获取I2C BUS操作句柄 */
if (TouchSetupI2c(g_coreData)) {
goto ERR_EXIT;
}
/* 创建Task用于监听处理中断业务 */
if (TouchIrqTaskInit(g_coreData)) {
goto ERR_EXIT;
}
/* 进行电源初始化配置及操作 */
if (TouchPowerInit(g_coreData)) {
goto ERR_EXIT;
}
/* 创建input设备文件 */
(void)mkdir("/dev/input", DEFAULT_DIR_MODE);
if (register_driver(TOUCH_DEVICE, &g_touchDevOps, TOUCH_DEVICE_MODE, NULL)) {
HDF_LOGE("%s: register touch dev failed", __func__);
goto ERR_EXIT;
}
HDF_LOGE("%s: exit succ", __func__);
return HDF_SUCCESS;
ERR_EXIT:
if (g_coreData->i2cClient.i2cHandle != NULL) {
DeviceHandleDestroy(g_coreData->i2cClient.i2cHandle);
g_coreData->i2cClient.i2cHandle = NULL;
}
OsalMemFree(g_coreData);
g_coreData = NULL;
return HDF_FAILURE;
}
static void TouchConfigInit(TouchCoreData *cd)
{
/* init waitqueue for poll */
__init_waitqueue_head(&cd->pollWait);
/* 配置i2c从地址、总线号、报点范围 */
cd->i2cClient.i2cCfg.addr = DRIVER_CHIP_I2C_ADDR;
cd->i2cClient.i2cCfg.busNum = I2C_BUS_NUM;
cd->inputCfg.solutionY = TOUCH_SOLUTION_Y;
/* 配置input设备类型,本例为Touch驱动 */
cd->inputDevType = INDEV_TYPE_TOUCH;
/* 配置reset、irq的gpio号,以及irq的中断触发方式 */
cd->rstGpioNum = RST_GPIO_OFFSET;
cd->intGpioNum = INT_GPIO_OFFSET;
cd->irqFlag = OSAL_IRQF_TRIGGER_FALLING;
}
配置及使用IO管脚
如下为reset和irq管脚的初始化配置,统一使用PAL接口实现对GPIO的操作,具体可参考PLATFORM提供的GPIO接口使用指导
配置I2C的IO管脚复用,以及其操作句柄的获取,可参考PLATFORM提供的
static int TouchSetupI2c(TouchCoreData *cd)
{
/* config I2C reuse I2C7 */
writel(I2C_REG_CFG, IO_DEVICE_ADDR(I2C7_DATA_REG_ADDR));
writel(I2C_REG_CFG, IO_DEVICE_ADDR(I2C7_CLK_REG_ADDR));
/* get i2c handle */
cd->i2cClient.i2cHandle = I2cOpen(cd->i2cClient.i2cCfg.busNum);
if (cd->i2cClient.i2cHandle == NULL) {
HDF_LOGE("open i2c failed");
return HDF_FAILURE;
}
HDF_LOGI("%s: exit succ", __func__);
return HDF_SUCCESS;
}
static int TouchIrqTaskInit(TouchCoreData *cd)
{
/* 初始化消息事件 */
int ret = LOS_EventInit(&g_touchEventIrq);
if (ret != HDF_SUCCESS) {
HDF_LOGE("LOS_EventInit failed, ret = %d", ret);
return HDF_FAILURE;
}
/* 注册中断 */
ret = GpioSetIrq(cd->intGpioNum, cd->irqFlag, IrqHandle, cd);
if (ret != 0) {
HDF_LOGE("register irq failed, ret %d", ret);
return ret;
}
/* 使能中断 */
ret = GpioEnableIrq(cd->intGpioNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("enable irq failed, ret %d", ret);
return HDF_FAILURE;
}
/* 创建中断处理Task,其负责input event数据的读取和解析 */
TSK_INIT_PARAM_S handleEventTask = {0};
UINT32 handleEventTaskID;
handleEventTask.pfnTaskEntry = (TSK_ENTRY_FUNC)TouchHandleEvent;
handleEventTask.uwStackSize = TASK_SIZE;
handleEventTask.pcName = "HdfTouchEventHandler";
handleEventTask.usTaskPrio = TASK_PRIO_LEVEL_TWO;
handleEventTask.uwResved = LOS_TASK_STATUS_DETACHED;
if (LOS_TaskCreate(&handleEventTaskID, &handleEventTask) != HDF_SUCCESS) {
HDF_LOGE("%s: LOS_TaskCreate fail, HdfTouchEventHandler", __func__);
return HDF_FAILURE;
}
HDF_LOGI("%s: exit succ", __func__);
return HDF_SUCCESS;
}
中断响应函数
Task处理函数
static void TouchHandleEvent(void)
{
InputEventData event;
TouchCoreData *cd = GetCoreData();
(void)memset_s(&event, sizeof(InputEventData), 0, sizeof(InputEventData));
while (true) {
int ret = LOS_EventRead(&g_touchEventIrq, EVENT_SYNC, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
if (ret != EVENT_SYNC) {
OsalMSleep(TASK_SLEEP_MS);
} else {
/* 报点事件的读取及解析 */
if (EventHandler(cd, &event) == HDF_SUCCESS) {
TouchWakeupPoll();
}
}
/* 使能中断 */
ret = GpioEnableIrq(cd->intGpioNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("enable irq failed, ret %d", ret);
}
if (cd->shouldStop) {
HDF_LOGE("%s: the event task should be stoped", __func__);
break;
}
}
}
创建及操作设备文件
/* 创建设备文件 */
register_driver(TOUCH_DEVICE, &g_touchDevOps, TOUCH_DEVICE_MODE, NULL);
/* 文件操作ops */
static const struct file_operations_vfs g_touchDevOps = {
.open = TouchOpen,
.close = TouchClose,
.read = NULL,
.write = NULL,
.seek = NULL,
.ioctl = TouchIoctl,
.mmap = NULL,
#ifndef CONFIG_DISABLE_POLL
.poll = TouchPoll,
#endif
.unlink = NULL,
};
/* Ioctl的操作方式 */
static int TouchIoctl(FAR struct file *filep, int cmd, unsigned long arg)
{
int ret;
if (filep == NULL) {
HDF_LOGE("%s: param is null", __func__);
return HDF_ERR_INVALID_PARAM;
}
switch (cmd) {
case INPUT_IOCTL_GET_EVENT_DATA:
ret = IoctlReadInputEvent(arg);
break;
case INPUT_IOCTL_GET_DEVICE_TYPE:
ret = IoctlGetDeviceType(arg);
break;
case INPUT_IOCTL_GET_CHIP_INFO:
ret = IoctlGetChipInfo(arg);
break;
default:
ret = 0;
HDF_LOGE("%s: cmd unknown, cmd = 0x%x", __func__, cmd);
break;
}