鸿蒙4.0:ilitek 触摸屏驱动适配HDF框架

一、关键源码文件:

1、GT911的器件驱动文件(基于该驱动修改成ILITEK驱动):
drivers/hdf_core/framework/model/input/driver/touchscreen/touch_gt911.c
2、HDF触摸屏平台驱动文件:
drivers/hdf_core/framework/model/input/driver/hdf_touch.c

二、驱动加载流程

首先加载平台驱动文件hdf_touch.c,下面是驱动入口。

struct HdfDriverEntry g_hdfTouchEntry = {
    .moduleVersion = 1,
    .moduleName = "HDF_TOUCH",
    .Bind = HdfTouchDriverBind, //驱动对外提供的服务能力,将相关的务接口绑定到HDF框架
    .Init = HdfTouchDriverProbe, 
    .Release = HdfTouchDriverRelease,
};

HDF_INIT(g_hdfTouchEntry);

执行函数HdfTouchDriverProbe:

static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device)
{
//************  此处省略   ***************
 //实现数据配置解析,解析触摸屏私有配置文件input_config.hcs下boardConfig下inputAttr、busConfig、pinConfig等各个子节点的属性
boardCfg = BoardConfigInstance(device);  

//只是申请空间并初始化结构体
    touchDriver = TouchDriverInstance();	
  
//经上述函数,获取到节点信息,利用信息进行初始化,打开i2c设备节点。配置i2c 时钟线数据线的寄存器
    ret = TouchDriverInit(touchDriver, boardCfg); 
   
//************  此处省略   ***************
}

下面开始实例化并加载器件驱动。

        touch_gt911.c文件的重要结构体:

struct HdfDriverEntry g_touchGoodixChipEntry = {
    .moduleVersion = 1,
    .moduleName = "HDF_TOUCH_GT911",
    .Init = HdfGoodixChipInit,
    .Release = HdfGoodixChipRelease,
};
 static struct TouchChipOps g_gt911ChipOps = {
    .Init = ChipInit,                            //关键结构体的初始化
    .Detect = ChipDetect,                       //获取触摸屏的信息,例如版本号
    .Resume = ChipResume,                      //触摸屏唤醒
    .Suspend = ChipSuspend,                   //触摸屏休眠
    .DataHandle = ChipDataHandle,            //中断处理
   .UpdateFirmware = UpdateFirmware,        //下发固件
   .SetAbility = SetAbility,               //设置按键值、坐标点信息等等
};

        其中的moduleName 属性的值必须要跟平台下的device_info.hcs文件中同属性的值相同,不然驱动无法加载。

首先执行初始化函数HdfGoodixChipInit:

static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device)
{
    TouchChipCfg *chipCfg = NULL;
    ChipDevice *chipDev = NULL;

//*************************  此处省略 ***********************

    chipCfg = ChipConfigInstance(device);     //实例化chipCfg 结构体,获取hcs节点信息,例如中断类型、总线类型、芯片版本等等信息

//*************************  此处省略 ***********************

    chipDev = ChipDeviceInstance();            //实例化chipDev 结构体

//*************************  此处省略 ***********************
    chipDev->chipCfg = chipCfg;
    chipDev->ops = &g_gt911ChipOps;
    chipDev->chipName = chipCfg->chipName;
    chipDev->vendorName = chipCfg->vendorName;

    if (RegisterChipDevice(chipDev) != HDF_SUCCESS) {
        goto EXIT1;
    }
}

再调用平台驱动函数RegisterChipDevice,一般来讲,触摸屏驱动一般是跑以下流程:

知道这个流程是怎么跑,我们就可以基于GT911的驱动,将ILITEK的驱动填充进去

三、基于GT911的原有驱动文件,转化为ILITEK驱动

调用完平台驱动函数RegisterChipDevice后,最后调用器件驱动函数ChipDetect,该函数主要完成触摸屏的上电、复位、申请中断,读取tp信息以及初始化ILITEK的协议。

ChipDetect函数代码如下:

void ilitek_set_pwr_on_xx(void)
{
 GpioSetDir(94, 1);    //HDF自带的GPIO操作函数
        GpioWrite(94, 1); 
}

void ilitek_reset_xx(void)
{
 
 GpioSetDir(111, 1);
         GpioWrite(111, 1); 
 OsalMSleep(10);

 GpioWrite(111, 0); 
 OsalMSleep(10);
 
 GpioWrite(111, 1); 
 OsalMSleep(1000);
}

void ilitek_request_irq_xx(void)
{
 GpioSetDir(112,0);
}

/*
global value 
	*/
static InputI2cClient *g_i2cClient = NULL;
static int32_t ChipDetect(ChipDevice *device)
{
g_i2cClient = &device->driver->i2cClient;    //全局变量
//******************************* 此处省略 *************************************
    ilitek_request_irq_xx();     //申请中断
    ilitek_set_pwr_on_xx();     //上电
    ilitek_reset_xx();           //复位
 
//******************************* 此处省略 ********************************   
 ret = api_protocol_init_func();             //协议初始化

 ret = ilitek_read_tp_info(true);            //读取tp信息,例如固件版本、ic版本、坐标最大值、最小值等等

//******************************* 此处省略 ********************************** 
}  

上述函数中,调用了ILITEK驱动中的API  api_protocol_init_func用于协议初始化 以及 ilitek_read_tp_info用于读取tp信息,我们不用做太多修改,直接套用ILITEK驱动原生的。

值得注意的是,原生的i2c读写的函数中用到的i2c_client,在这里要替换成HDF i2c 适配层

的InputI2cClient结构体以及HDF特定的读写函数,要对ILITEK驱动中的读写函数做一下修改才能读写,如下:
 

int ilitek_i2c_write_and_read(uint8_t *cmd, int write_len, int delay, uint8_t *data, int read_len)
{
 int ret = 0;
 if(delay > 0)
 {
  ret = InputI2cWrite(g_i2cClient,cmd,write_len);
  mdelay(delay);
  ret = InputI2cRead(g_i2cClient,cmd,write_len, data,read_len);
 }else if (delay == 0){
  ret = InputI2cRead(g_i2cClient,cmd,write_len, data,read_len);
 }
 return ret;
}

ChipDetect函数执行完后,回到平台驱动的ChipDriverInit函数,然后申请中断:

static int32_t ChipDriverInit(ChipDevice *chipDev)
{
//********************** 此处省略***************************************

    if ((chipDev->ops == NULL) || (chipDev->ops->Detect == NULL)) {
        return HDF_FAILURE;
    }

    while (count --) {
        OsalMSleep(100); // 100 : wait 100msthen try one time
        ret = chipDev->ops->Detect(chipDev);             //作上电、复位等初始化操作
        if (ret == HDF_SUCCESS) {
            break;
        }
//********************** 此处省略***************************************
    ret = SetupChipIrq(chipDev);                        //申请中断
    CHECK_RETURN_VALUE(ret);
    return HDF_SUCCESS;
}

SetupChipIrq函数如下:

static int32_t SetupChipIrq(ChipDevice *chipDev)
{
//*************************  此处省略 *********************************
    uint16_t intGpioNum = chipDev->boardCfg->pins.intGpio;      //中断引脚配置在gt911的私有配置文件
    uint16_t irqFlag = chipDev->chipCfg->bus.chipI2c.irqFlag;      //中断标志配置在gt911的私有配置文件

//*************************  此处省略 *********************************
    irqFlag |= GPIO_IRQ_USING_THREAD;
    ret = GpioSetIrq(intGpioNum, irqFlag, IrqHandle, chipDev->driver);   //IrqHandle为中断处理函数

//*************************  此处省略 *********************************
    ret = GpioEnableIrq(intGpioNum);  //使能中断

}

中断处理函数最终调用GT911.C中的函数ChipDataHandle,如下图:

static int32_t ChipDataHandle(ChipDevice *device)
{
 int ret;
 ret = ilitek_read_data_and_report_3XX(device->driver);
 if(ret == 0){
  tp_log_err("------ liyj ----- ilitek_read_data_and_report_3XX success \n");
 }else {
  return HDF_FAILURE;
 }
 return HDF_SUCCESS;
}

ChipDataHandle函数主要是处理坐标信息的设置和上报,直接将ILITEK驱动的上报函数ilitek_read_data_and_report_3XX搬过来即可。但要注意得是,要在原生的基础上作出以下修改:

        1、传入参数TouchDriver *driver
        2、原生的函数上报坐标信息使用的是struct input_dev结构体,这里要换成HDF 框架定义的 InputDevice 结构体
修改完如下:

int ilitek_read_data_and_report_3XX(TouchDriver *driver)
{
//**************************************** 此处省略***************************

//struct input_dev *input = ilitek_data->input_dev;     原生的写法,注释掉

input = driver->inputDev;     //在外面定义了全局变量 InputDevice *input;

//**************************************** 此处省略***************************
}

再注释掉HDF 触摸驱动框架自带的坐标信息上报函数,如下:

static void EventHandle(TouchDriver *driver, ChipDevice *chipDev)
{
    int32_t ret;
    if ((chipDev->ops == NULL) || (chipDev->ops->DataHandle == NULL))  	{
        return;
    }

    ret = chipDev->ops->DataHandle(chipDev);
    // if (ret == HDF_SUCCESS) {
        // InputFrameReport(driver);  //注释
    // }
}

做完上述操作好,回到hdf_touch.c,执行器件驱动函数SetAbility进行按键事件、属性设置:

int32_t RegisterTouchChipDevice(ChipDevice *chipDev)
{
// ************************ 此处省略 ********************************
    ret = DeviceBindDriver(chipDev);

    ret = ChipDriverInit(chipDev);
    inputDev = InputDeviceInstance(chipDev);

    ret = RegisterInputDevice(inputDev);

// ************************ 此处省略 ********************************
    chipDev->driver->inputDev = inputDev;
    chipDev->ops->SetAbility(chipDev);    //设置按键事件、属性
    return HDF_SUCCESS;

}

SetAbility函数直接套用gt911.c原生的:

static void SetAbility(ChipDevice *device)
{
    device->driver->inputDev->abilitySet.devProp[0] = SET_BIT(INPUT_PROP_DIRECT);
    device->driver->inputDev->abilitySet.eventType[0] = SET_BIT(EV_SYN) |
        SET_BIT(EV_KEY) | SET_BIT(EV_ABS);
    device->driver->inputDev->abilitySet.absCode[0] = SET_BIT(ABS_X) | SET_BIT(ABS_Y);
    device->driver->inputDev->abilitySet.absCode[1] = SET_BIT(ABS_MT_POSITION_X) |
        SET_BIT(ABS_MT_POSITION_Y) | SET_BIT(ABS_MT_TRACKING_ID);
    device->driver->inputDev->abilitySet.keyCode[KEY_CODE_4TH] = SET_BIT(KEY_UP) | SET_BIT(KEY_DOWN);
    device->driver->inputDev->attrSet.axisInfo[ABS_X].min = 0;
    device->driver->inputDev->attrSet.axisInfo[ABS_X].max = device->boardCfg->attr.resolutionX - 1;

//*************************************此处省略***********************

}


做到这一步,基本上已经移植完毕。接下来就是烧录验证。

ilitek2510 是一款常见的 USB 触摸屏控制器芯片,Linux 平台下可以使用 HID 触摸屏驱动来支持 ilitek2510 触摸屏。 以下是步骤: 1. 确保系统已经加载了 hid-multitouch 驱动,可以使用以下命令来检查: ``` lsmod | grep hid_multitouch ``` 如果没有输出,则需要加载该驱动: ``` sudo modprobe hid-multitouch ``` 2. 连接 ilitek2510 触摸屏,并用以下命令来检测是否能够识别: ``` dmesg | grep input ``` 如果能够识别,则会输出如下信息: ``` input: ILITEK ILITEK-TP as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:22B8:2E82.0001/input/input3 hid-generic 0003:22B8:2E82.0001: input,hidraw0: USB HID v1.10 Pointer [ILITEK ILITEK-TP] on usb-0000:00:14.0-3/input0 ``` 其中,hidraw0 就是触摸屏的设备号。 3. 安装 xinput 工具,可以使用以下命令进行安装: ``` sudo apt-get install xinput ``` 4. 使用以下命令来调整触摸屏的参数: ``` xinput set-prop <device id> "Device Accel Velocity Scaling" <value> ``` 其中,device id 就是之前获取到的 hidraw 设备号,value 是一个浮点数,代表加速度的值。可以根据实际情况进行调整。 5. 如果需要在系统启动时自动加载 hid-multitouch 驱动和设置触摸屏参数,可以将以下脚本保存为 /etc/init.d/touchscreen,并授予可执行权限: ``` #!/bin/bash ### BEGIN INIT INFO # Provides: touchscreen # Required-Start: $local_fs $remote_fs $syslog # Required-Stop: $local_fs $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start touchscreen # Description: Enable support for ilitek2510 touchscreen on boot ### END INIT INFO case "$1" in start) modprobe hid-multitouch xinput set-prop <device id> "Device Accel Velocity Scaling" <value> ;; stop) ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0 ``` 然后使用以下命令将脚本添加到启动项中: ``` sudo update-rc.d touchscreen defaults ``` 以上就是在 Linux 平台下使用 ilitek2510 触摸屏驱动方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值