7.9.5. 设计说明
7.9.5.1. 源码说明
源代码位于:linux-5.x/drivers/input/touchscreen/zx.c
7.9.5.2. 模块架构
RTP驱动基于Linux内核中的input子系统实现,其关系如下图:
7.9.5.3. 关键流程设计
7.9.5.3.1. 初始化流程
RTP模块完全遵循platform_driver的通用初始化流程,申请regs资源、clk、reset, 还需要注册一个input设备,使用input子系统提供的注册接口input_register_device():
int __must_check input_register_device(struct input_dev *);
参数struct input_dev记录了该input设备的信息,其中关键信息有:设备名称、 open/close接口、KEY类型、坐标范围等。RTP控制器的input信息注册如下:
rtp->idev = idev;
idev->name = pdev->name;
idev->phys = AIC_RTP_NAME "/input0";
idev->open = aic_rtp_open;
idev->close = aic_rtp_close;
idev->id.bustype = BUS_HOST;
idev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
input_set_capability(idev, EV_KEY, BTN_TOUCH);
input_set_abs_params(idev, ABS_X, 0, AIC_RTP_MAX_VAL, rtp->fuzz, 0);
input_set_abs_params(idev, ABS_Y, 0, AIC_RTP_MAX_VAL, rtp->fuzz, 0);
if (rtp->pressure_det)
input_set_abs_params(idev, ABS_PRESSURE, 0, AIC_RTP_MAX_VAL,
rtp->fuzz, 0);
7.9.5.3.2. 中断处理流程
RTP控制器采集的数据完全依赖中断来上报给用户态,包括触摸位置、按下、抬起信息。 流程如下图:
“启动manual worker”和“启动smp worker”分别是对应手动模式、非周期模式的采样流程,因为这两种情况下都会有一些延迟操作,所以使用worker方式来处理。实际运行期间RTP只可能工作在一种单一模式,所以运行中只会有一个worker在参与调度。
其中,检查的异常事件类型及处理方式如下图:
其中,“数据不完整”仅在自动模式才会出现,实际上有三种原因导致不完整:
采样循环不完整:Sample Cycle Incomplete,一组采样点还没有完成就发生了抬起事件;
数据超限:Data Over Uncertain Range,数据超出了有效范围;
FIFO下溢:FIFO上溢意味着数据有效、软件读慢了,所以还可以继续数据;如果是下溢,意味着FIFO中的数据分组排列已经乱了,所以直接丢弃。
7.9.5.3.3. 手动模式的采样流程
手动模式,需要通过软件触发的方式告诉RTP控制器要采集什么样的数据,所以采集样本的电信号配置、采集间隔、是否打开按压检测等,都需要在驱动中来妥善安排。 因为每次中断来了后,手动模式需要做的处理较多,而且有一些延迟处理,所以在驱动中使用了一个worker专门处理手动模式的流程(接口aic_rtp_manual_worker())。 手动模式的处理流程较复杂,建议通常情况下采样自动模式。
上图中,在蓝色方框的后面都会有一个判断:如果当前是否抬起状态,如果是就打开按压检测。为了流程的主干更加清晰,所以图中未标注出来。
7.9.5.4. 数据结构设计
7.9.5.4.1. aic_rtp_dev
管理RTP控制器的设备资源。
struct aic_rtp_dev {
struct platform_device *pdev;
struct attribute_group attrs;
struct clk *clk;
struct reset_control *rst;
struct device *dev;
struct input_dev *idev;
void __iomem *regs;
u32 irq;
u32 pclk_rate;
bool two_points;
bool pressure_det;
bool ignore_fifo_data;
enum aic_rtp_mode mode;
u32 max_press;
u32 smp_period;
u32 x_plate;
u32 y_plate;
u32 fuzz;
struct workqueue_struct *workq;
struct work_struct event_work;
u32 intr;
u32 fcr;
struct aic_rtp_dat latest;
enum aic_rtp_manual_mode_status mms;
};
7.9.5.5. 接口设计
以下接口是Input子系统需要的标准接口。
7.9.5.5.1. aic_rtp_open
函数原型 |
static int aic_rtp_open(struct input_dev *dev) |
---|---|
功能说明 |
打开RTP设备,驱动会使能RTP控制器 |
参数定义 |
dev - 指向当前的input设备 |
返回值 |
0,成功; < 0,失败 |
注意事项 |
7.9.5.5.2. aic_rtp_close
函数原型 |
static void aic_rtp_close(struct input_dev *dev) |
---|---|
功能说明 |
关闭RTP设备,驱动会关闭RTP控制器 |
参数定义 |
dev - 指向当前的input设备 |
返回值 |
无 |
注意事项 |