Linux驱动开发学习笔记-电容触摸屏驱动

<电容触摸屏驱动框架>
电容触摸屏驱动其实是以下几种 linux 驱动框架的组合:
① IIC 设备驱动,因为电容触摸 IC 基本都是 IIC 接口的,因此大框架就是 IIC 设备驱动。
② 通过中断引脚(INT)向 linux 内核上报触摸信息,因此需要用到 linux 中断驱动框架。坐标的上报在中断服务函数中完成。
③ 触摸屏的坐标信息、屏幕按下和抬起信息都属于 linux 的 input 子系统,因此向 linux 内核上报触摸屏坐标信息就得使用 input 子系统。


1. 多点触摸(MT)协议详解
   1). MT 协议被分为两种类型,TypeA 和 TypeB,这两种类型的区别如下:
       TypeA:适用于触摸点不能被区分或者追踪,此类型的设备上报原始数据(此类型在实际使用中非常少!)。
       TypeB:适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备通过 slot 更新某一个触摸点的信息。

   2). 触摸点的信息通过一系列的 ABS_MT 事件(有的资料也叫消息)上报给 linux 内核,
       只有ABS_MT 事件是用于多点触摸的,ABS_MT 事件定义在文件 include/uapi/linux/input.h 中。

       在众多的 ABS_MT 事件中,最常用的就是 ABS_MT_SLOT 、ABS_MT_POSITION_X 、ABS_MT_POSITION_Y 和 ABS_MT_TRACKING_ID 。
       ABS_MT_SLOT:用来上报触摸点 ID
       ABS_MT_POSITION_X/ABS_MT_POSITION_Y:用来上报触摸点的 (X,Y) 坐标信息
       ABS_MT_TRACKING_ID:对于 Type B 类型设 备,用来区分触摸点

   3). 对于 TypeA 类型的设备,通过 input_mt_sync()函数来隔离不同的触摸点数据信息:
    void input_mt_sync(struct input_dev *dev)
        input_mt_sync()会触发 SYN_MT_REPORT 事件,通知接收者获取当前触摸数据,并且准备接收下一个触摸点数据。

       对于 TypeB 类型的设备,上报触摸点信息的时候需要通过 input_mt_slot()函数区分是哪一个触摸点:
    void input_mt_slot(struct input_dev *dev, int slot)    
       input_mt_slot()函数会触发 ABS_MT_SLOT 事件,此事件会告诉接收者当前正在更新的是哪个触摸点(slot)的数据。

       不管是哪个类型的设备,最终都要调用 input_sync()函数来标识多点触摸信息传输完成,
       告诉接收者处理之前累计的所有消息,并且准备好下一次接收。

   4). 对于 TypeA 设备,内核驱动需要一次性将触摸屏上所有的触摸点信息全部上报,
       每个触摸点的信息在本次上报事件流中的顺序不重要,因为事件的过滤和手指(触摸点)跟踪是在内核空间处理的。

   5). TypeB 设备驱动需要给每个识别出来的触摸点分配一个 slot,后面使用这个 slot 来上报触摸点信息。
        可以通过 slot 的 ABS_MT_TRACKING_ID 来新增、替换或删除触摸点。一个非负数的 ID 表示一个有效的触摸点,-1 这个 ID 表示未使用 slot。

   6). 有些设备识别或追踪的触摸点信息要比他上报的多,这些设备驱动应该给硬件上报的每个触摸点分配一个 Type B 的 slot。
        一旦检测到某一个 slot 关联的触摸点 ID 发生了变化,驱动就应该改变这个 slot 的 ABS_MT_TRACKING_ID,使这个 slot 失效。
        如果硬件设备追踪到了比他正在上报的还要多的触摸点,那么驱动程序应该发送 BTN_TOOL_*TAP 消息,并且调用
        input_mt_report_pointer_emulation()函数,将此函数的第二个参数 use_count 设置为 false。

   7). TypeA 触摸点信息上报时序(以 2 个触摸点为例)
    ABS_MT_POSITION_X x[0]         →  对应 input_report_abs函数    
    ABS_MT_POSITION_Y y[0]     →  对应 input_report_abs函数
    SYN_MT_REPORT        →  对应 input_mt_sync函数
    ABS_MT_POSITION_X x[1]     →  对应 input_report_abs函数
    ABS_MT_POSITION_Y y[1]     →  对应 input_report_abs函数
    SYN_MT_REPORT        →  对应 input_mt_sync函数
    SYN_REPORT        →  对应 input_sync函数

   8). TypeB 触摸点信息上报时序
    ABS_MT_SLOT 0         →  对应 input_mt_slot函数
    ABS_MT_TRACKING_ID 45    →  对应 input_mt_report_slot_state函数
    ABS_MT_POSITION_X x[0]     →  对应 input_report_abs函数
    ABS_MT_POSITION_Y y[0]    →  对应 input_report_abs函数
    ABS_MT_SLOT 1         →  对应 input_mt_slot函数
    ABS_MT_TRACKING_ID 46    →  对应 input_mt_report_slot_state函数
    ABS_MT_POSITION_X x[1]     →  对应 input_report_abs函数
    ABS_MT_POSITION_Y y[1]     →  对应 input_report_abs函数
    SYN_REPORT        →  对应 input_sync函数

   9). MT 其他事件的使用
       ABS_MT_TOOL_TYPE 事件用于上报触摸工具类型,目前的协议支持MT_TOOL_FINGER(手指)、MT_TOOL_PEN(笔)
       和 MT_TOOL_PALM(手掌)这三种触摸设备类型,使用 input_mt_report_slot_state 函数来完成上报触摸工具类型工作。

2. 多点触摸所使用到的 API 函数
    input_mt_init_slots 函数
        用于初始化 MT 的输入 slots        
            
    input_mt_slot 函数
        用于 Type B 类型,此函数用于产生 ABS_MT_SLOT 事件,上报触摸点坐标数据

    input_mt_report_slot_state 函数
        用于 Type B 类型,用于产生 ABS_MT_TRACKING_ID 和 ABS_MT_TOOL_TYPE事件

    input_report_abs 函数
        TypeA 和 Type B 类型都使用此函数上报触摸点坐标信息

    input_mt_report_pointer_emulation 函数
        追踪到的触摸点数量多于当前上报的数量,
        驱动程序使用 BTN_TOOL_TAP 事件来通知用户空间当前追踪到的触摸点总数量,
        然后调用 input_mt_report_pointer_emulation 函数将 use_count 参数设置为 false。

3. devm_request_threaded_irq 函数:
    ①用于申请中断,作用和 request_irq 函数类似。            
    ②此函数的作用是中断线程化。

    中断线程化以后中断将作为内核线程运行,而且也可以被赋予不同的优先级,任务的优先级可能比中断线程的优先级高,
    这样做的目的就是保证高优先级的任务能被优先处理。虽然中断下半部可以被延迟处理,但是依旧先于线程执行,
    中断线程化可以让这些比较耗时的下半部与进程进行公平竞争。

    要注意,并不是所有的中断都可以被线程化,重要的中断就不能这么操作,需要自己根据实际情况去衡量。

4. 在 linux 内核中有很多的申请资源类的 API 函数都有对应的“devm_”前缀版本,
    使用“devm_”前缀的函数申请到的资源可以由系统自动释放,不需要我们手动处理。
    带有“devm_”前缀的都是一些和设备资源管理有关的函数。


 

你可能感兴趣的:(linux,驱动开发,学习)