Linux驱动开发

您所在的位置:网站首页 触摸屏驱动原理 Linux驱动开发

Linux驱动开发

#Linux驱动开发| 来源: 网络整理| 查看: 265

电容触摸屏 一、Linux电容触摸屏驱动框架

电容触摸驱动的基本原理可参考​​Linux裸机开发|电容触摸屏实验​​一文。电容触摸 IC 基本都是 I2C 接口的,因此大框架就是 I2C 设备驱动;通过中断引脚(INT)向内核上报触摸信息,因此需要用到中断驱动框架;触摸屏的坐标信息、屏幕按下和抬起信息都属于 input 子系统,因此需要使用 input 子系统

1.1 多点触摸协议

I2C 驱动、中断驱动、 input 子系统在之前的文章中已经介绍过了,下面主要介绍 input 子系统下的多点电容触摸协议(Multi-touch,简称 MT)

触摸点的信息通过 ABS_MT 事件上报给内核,ABS_MT 事件定义在文件 include/uapi/linux/input.h 中,

#define ABS_MT_SLOT 0x2f /* 最常用:用于上报触摸点ID */#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */#define ABS_MT_POSITION_X 0x35 /* 用于上报触摸点的X坐标信息 */#define ABS_MT_POSITION_Y 0x36 /* 用于上报触摸点的Y坐标信息 */#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */#define ABS_MT_TRACKING_ID 0x39 /* 用于区分触摸点 */#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */#define ABS_MT_TOOL_X 0x3c /* Center X tool position */#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */

MT 协议被分为两种类型:​Type A​ 和 ​Type B​

Type A:适用于触摸点不能被区分或者追踪,此类型设备上报原始数据(较少用)

通过 ​​input_mt_sync(struct input_dev *dev)​​函数来隔离不同的触摸点数据信息,该函数会触发 SYN_MT_REPORT 事件,此事件会通知接收者获取当前触摸数据,并且准备接收下一个触摸点数据

input_mt_sync(struct input_dev *dev)//input_dev:用于指定具体的 input_dev 设备

​Type A 触摸点信息上报时序​:编写Type A类型的多点触摸驱动时,需要按照下面的时序上报坐标信息

//以两点触摸为例ABS_MT_POSITION_X x[0] //上报第一个触摸点的X坐标信息,通过input_report_abs函数实现ABS_MT_POSITION_Y y[0] //上报第一个触摸点的Y坐标信息,通过input_report_abs函数实现SYN_MT_REPORT //上报SYN_MT_REPORT事件,通过调用input_mt_sync函数实现ABS_MT_POSITION_X x[1] //上报第二个触摸点的X坐标信息,通过input_report_abs函数实现ABS_MT_POSITION_Y y[1] //上报第二个触摸点的Y坐标信息,通过input_report_abs函数实现SYN_MT_REPORT //上报SYN_MT_REPORT事件,通过调用input_mt_sync函数实现SYN_REPORT //上报SYN_REPORT事件,通过调用input_sync函数实现

Type A 类型触摸点信息上报实例

static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) { ...... ret = st1232_ts_read_data(ts); //获取所有触摸点信息 if (ret < 0) goto end; /* 按照Type A类型轮流上报所有的触摸点信息 */ for (i = 0; i < MAX_FINGERS; i++) { if (!finger[i].is_valid) continue; input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t); input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x); input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y); //每上报完一个触摸点坐标,都要调用以下函数上报一个 SYN_MT_REPOR input_mt_sync(input_dev); count++; } ...... /* 每上报完一轮触摸点信息就调用一次input_sync函数,发送SYN_REPORT事件 */ input_sync(input_dev);end: return IRQ_HANDLED;}Type B:适用于有硬件追踪并能区分触摸点的触摸设备,通过 slot 更新某个触摸点的信息

通过 ​​input_mt_slot(struct input_dev *dev, int slot)​​函数区分是哪一个触摸点,函数会触发 ABS_MT_SLOT 事件,此事件会告诉接收者当前正在更新的是哪个触摸点(slot)的数据

void input_mt_slot(struct input_dev *dev, int slot)//input_dev:用于指定具体的 input_dev 设备//slot:用于指定当前上报的是哪个触摸点信息

​Type B 触摸点信息上报时序​:编写Type B类型的多点触摸驱动时,需要按照下面的时序上报坐标信息

//以两点触摸为例ABS_MT_SLOT 0 //上报触摸点对应的SLOT(即触摸点ID),通过input_mt_slot函数实现ABS_MT_TRACKING_ID 45 //每个触摸点关联一个ID,修改该ID可进行触摸点的添加、替换或删除,通过input_mt_report_slot_state函数实现ABS_MT_POSITION_X x[0] //上报第一个触摸点的X坐标信息,通过input_report_abs函数实现ABS_MT_POSITION_Y y[0] //上报第一个触摸点的Y坐标信息,通过input_report_abs函数实现ABS_MT_SLOT 1 //上报触摸点对应的SLOT(即触摸点ID),通过input_mt_slot函数实现ABS_MT_TRACKING_ID 46 //每个触摸点关联一个ID,修改该ID可进行触摸点的添加、替换或删除,通过input_mt_report_slot_state函数实现ABS_MT_POSITION_X x[1] //上报第二个触摸点的X坐标信息,通过input_report_abs函数实现ABS_MT_POSITION_Y y[1] //上报第二个触摸点的Y坐标信息,通过input_report_abs函数实现SYN_REPORT //上报SYN_REPORT事件,通过调用input_sync函数实现

Type B 类型触摸点信息上报实例

static void ili210x_report_events(struct input_dev *input, const struct touchdata *touchdata) { int i; bool touch; unsigned int x, y; const struct finger *finger; for (i = 0; i < MAX_TOUCHES; i++) { input_mt_slot(input, i); //上报 ABS_MT_SLOT 事件 finger = &touchdata->finger[i]; touch = touchdata->status & (1 x_low | (finger->x_high y_low | (finger->y_high dev, client->irq, NULL, xxx_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, &xxx); ...... /* 3, input 设备申请与初始化 */ input = devm_input_allocate_device(&client->dev); input->name = client->name; input->id.bustype = BUS_I2C; input->dev.parent = &client->dev; ...... /* 4,初始化 input 和 MT */ __set_bit(EV_ABS, input->evbit); __set_bit(BTN_TOUCH, input->keybit); input_set_abs_params(input, ABS_X, 0, width, 0, 0); input_set_abs_params(input, ABS_Y, 0, height, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_X,0, width, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y,0, height, 0, 0); input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); ...... /* 5,注册 input_dev */ input_register_device(input); ......}

使用“ devm_”前缀的函数申请到的资源可以由系统自动释放,不需要我们手动处理

上报坐标信息:在中断服务程序中上报读取到的坐标信息static irqreturn_t xxx_handler(int irq, void *dev_id) { int num; /* 触摸点数量 */ int x[n], y[n]; /* 保存坐标值 */ /* 1、从触摸芯片获取各个触摸点坐标值 */ ...... /* 2、上报每一个触摸点坐标 */ for (i = 0; i < num; i++) { input_mt_slot(input, id); input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, x[i]); input_report_abs(input, ABS_MT_POSITION_Y, y[i]); } ...... input_sync(input); ...... return IRQ_HANDLED;} 二、电容触摸屏实验

本实验以ATK7016(7 寸 1024*600 分辨率)屏幕所使用的 FT5426 触摸芯片为例,讲解如何编写多点电容触摸驱动,硬件原理图参考​​Linux裸机开发|电容触摸屏实验​​一文

2.1 修改设备树修改或添加pinctrl节点:FT5426 触摸芯片用到了复位 IO、中断 IO、I2C2 的 SCL 和 SDA共4个 IO

如有默认的 pinctrl_tsc 子节点,则直接添加如下中断引脚信息;若没有则在iomuxc节点下自行创建

pinctrl_tsc: tscgrp { fsl,pins = ;};

复位引脚是SNVS_TAMPER9,因此在iomuxc_snvs节点下添加复位引脚信息

pinctrl_tsc_reset: tsc_reset { fsl,pins = ;};

I2C2 的 SCL 和 SDA 属于 I2C2,一般默认已经添加,无需修改

pinctrl_i2c2: i2c2grp { fsl,pins = ;};添加子节点:FT5426 触摸 IC 挂载 I2C2 下,因此需要向 I2C2 节点下添加一个子节点,用于描述 FT5426&i2c2 { clock_frequency = ; pinctrl-names = "default"; pinctrl-0 = ; status = "okay"; /****************************/ /* 省略掉其他的设备节点 */ /****************************/ ft5426: ft5426@38 { //器件地址为0x38 compatible = "edt,edt-ft5426"; reg = ; //描述器件地址为0x38 pinctrl-names = "default"; pinctrl-0 = < &pinctrl_tsc &pinctrl_tsc_reset >; interrupt-parent = ; interrupts = ; reset-gpios = ; interrupt-gpios = ; };};检查PIN是否冲突:检查pinctrl中设置以及设备节点中指定的引脚有没有被别的外设使用

保存修改后,在kernel主目录下使用“make dtbs”命令编译设备树,使用新的设备树文件启动Llinux系统

2.2 驱动程序编写

新建 ft5x06.c 驱动文件

#define MAX_SUPPORT_POINTS 5 /* 5点触摸 */#define TOUCH_EVENT_DOWN 0x00 /* 按下 */#define TOUCH_EVENT_UP 0x01 /* 抬起 */#define TOUCH_EVENT_ON 0x02 /* 接触 */#define TOUCH_EVENT_RESERVED 0x03 /* 保留 *//* FT5X06寄存器相关宏定义 */#define FT5X06_TD_STATUS_REG 0X02 /* 状态寄存器地址 */#define FT5x06_DEVICE_MODE_REG 0X00 /* 模式寄存器 */#define FT5426_IDG_MODE_REG 0XA4 /* 中断模式 */#define FT5X06_READLEN 29 /* 要读取的寄存器个数 */struct ft5x06_dev { struct device_node *nd; /* 设备节点 */ int irq_pin,reset_pin; /* 中断和复位IO */ int irqnum; /* 中断号 */ void *private_data; /* 私有数据 */ struct input_dev *input; /* input结构体 */ struct i2c_client *client; /* I2C客户端 */};static struct ft5x06_dev ft5x06;/* 复位FT5X06 */static int ft5x06_ts_reset(struct i2c_client *client, struct ft5x06_dev *dev){ int ret = 0; if (gpio_is_valid(dev->reset_pin)) { /* 检查IO是否有效 */ /* 申请复位IO,并且默认输出低电平 */ ret = devm_gpio_request_one(&client->dev, dev->reset_pin, GPIOF_OUT_INIT_LOW, "edt-ft5x06 reset"); if (ret) { return ret; } msleep(5); gpio_set_value(dev->reset_pin, 1); /* 输出高电平,停止复位 */ msleep(300); } return 0;}/* 从FT5X06读取多个寄存器数据 */static int ft5x06_read_regs(struct ft5x06_dev *dev, u8 reg, void *val, int len){ int ret; struct i2c_msg msg[2]; struct i2c_client *client = (struct i2c_client *)dev->client; /* msg[0]为发送要读取的首地址 */ msg[0].addr = client->addr; /* ft5x06地址 */ msg[0].flags = 0; /* 标记为发送数据 */ msg[0].buf = ® /* 读取的首地址 */ msg[0].len = 1; /* reg长度*/ /* msg[1]读取数据 */ msg[1].addr = client->addr; /* ft5x06地址 */ msg[1].flags = I2C_M_RD; /* 标记为读取数据*/ msg[1].buf = val; /* 读取数据缓冲区 */ msg[1].len = len; /* 要读取的数据长度*/ ret = i2c_transfer(client->adapter, msg, 2); if(ret == 2) { ret = 0; } else { ret = -EREMOTEIO; } return ret;}/* 向ft5x06多个寄存器写入数据 */static s32 ft5x06_write_regs(struct ft5x06_dev *dev, u8 reg, u8 *buf, u8 len){ u8 b[256]; struct i2c_msg msg; struct i2c_client *client = (struct i2c_client *)dev->client; b[0] = reg; /* 寄存器首地址 */ memcpy(&b[1],buf,len); /* 将要写入的数据拷贝到数组b里面 */ msg.addr = client->addr; /* ft5x06地址 */ msg.flags = 0; /* 标记为写数据 */ msg.buf = b; /* 要写入的数据缓冲区 */ msg.len = len + 1; /* 要写入的数据长度 */ return i2c_transfer(client->adapter, &msg, 1);}/* 向ft5x06指定寄存器写入指定的值,写一个寄存器 */static void ft5x06_write_reg(struct ft5x06_dev *dev, u8 reg, u8 data){ u8 buf = 0; buf = data; ft5x06_write_regs(dev, reg, &buf, 1);}/* FT5X06中断服务函数 */static irqreturn_t ft5x06_handler(int irq, void *dev_id){ struct ft5x06_dev *multidata = dev_id; u8 rdbuf[29]; int i, type, x, y, id; int offset, tplen; int ret; bool down; offset = 1; /* 偏移1,也就是0X02+1=0x03,从0X03开始是触摸值 */ tplen = 6; /* 一个触摸点有6个寄存器来保存触摸值 */ memset(rdbuf, 0, sizeof(rdbuf)); /* 清除 */ /* 读取FT5X06触摸点坐标从0X02寄存器开始,连续读取29个寄存器 */ ret = ft5x06_read_regs(multidata, FT5X06_TD_STATUS_REG, rdbuf, FT5X06_READLEN); if (ret) { goto fail; } /* 上报每一个触摸点坐标 */ for (i = 0; i < MAX_SUPPORT_POINTS; i++) { u8 *buf = &rdbuf[i * tplen + offset]; /* 以第一个触摸点为例,寄存器TOUCH1_XH(地址0X03),各位描述如下: * bit7:6 Event flag 0:按下 1:释放 2:接触 3:没有事件 * bit5:4 保留 * bit3:0 X轴触摸点的11~8位。 */ type = buf[0] >> 6; /* 获取触摸类型 */ if (type == TOUCH_EVENT_RESERVED) continue; /* 我们所使用的触摸屏和FT5X06是反过来的 */ x = ((buf[2] 4) & 0x0f; down = type != TOUCH_EVENT_UP; input_mt_slot(multidata->input, id); input_mt_report_slot_state(multidata->input, MT_TOOL_FINGER, down); if (!down) continue; input_report_abs(multidata->input, ABS_MT_POSITION_X, x); input_report_abs(multidata->input, ABS_MT_POSITION_Y, y); } input_mt_report_pointer_emulation(multidata->input, true); input_sync(multidata->input);fail: return IRQ_HANDLED;}/* FT5x06中断初始化 */static int ft5x06_ts_irq(struct i2c_client *client, struct ft5x06_dev *dev){ int ret = 0; /* 1,申请中断GPIO */ if (gpio_is_valid(dev->irq_pin)) { ret = devm_gpio_request_one(&client->dev, dev->irq_pin, GPIOF_IN, "edt-ft5x06 irq"); if (ret) { dev_err(&client->dev, "Failed to request GPIO %d, error %d\n", dev->irq_pin, ret); return ret; } } /* 2,申请中断,client->irq就是IO中断, */ ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, ft5x06_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, &ft5x06); if (ret) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); return ret; } return 0;}/* i2c驱动的probe函数,当驱动与设备匹配以后此函数就会执行 */static int ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){ int ret = 0; ft5x06.client = client; /* 1,获取设备树中的中断和复位引脚 */ ft5x06.irq_pin = of_get_named_gpio(client->dev.of_node, "interrupt-gpios", 0); ft5x06.reset_pin = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0); /* 2,复位FT5x06 */ ret = ft5x06_ts_reset(client, &ft5x06); if(ret < 0) { goto fail; } /* 3,初始化中断 */ ret = ft5x06_ts_irq(client, &ft5x06); if(ret < 0) { goto fail; } /* 4,初始化FT5X06 */ ft5x06_write_reg(&ft5x06, FT5x06_DEVICE_MODE_REG, 0); /* 进入正常模式 */ ft5x06_write_reg(&ft5x06, FT5426_IDG_MODE_REG, 1); /* FT5426中断模式 */ /* 5,input设备注册 */ ft5x06.input = devm_input_allocate_device(&client->dev); if (!ft5x06.input) { ret = -ENOMEM; goto fail; } ft5x06.input->name = client->name; ft5x06.input->id.bustype = BUS_I2C; ft5x06.input->dev.parent = &client->dev; __set_bit(EV_KEY, ft5x06.input->evbit); __set_bit(EV_ABS, ft5x06.input->evbit); __set_bit(BTN_TOUCH, ft5x06.input->keybit); input_set_abs_params(ft5x06.input, ABS_X, 0, 1024, 0, 0); input_set_abs_params(ft5x06.input, ABS_Y, 0, 600, 0, 0); input_set_abs_params(ft5x06.input, ABS_MT_POSITION_X,0, 1024, 0, 0); input_set_abs_params(ft5x06.input, ABS_MT_POSITION_Y,0, 600, 0, 0); ret = input_mt_init_slots(ft5x06.input, MAX_SUPPORT_POINTS, 0); if (ret) { goto fail; } ret = input_register_device(ft5x06.input); if (ret) goto fail; return 0;fail: return ret;}/* i2c驱动的remove函数,移除i2c驱动的时候此函数会执行 */static int ft5x06_ts_remove(struct i2c_client *client){ /* 释放input_dev */ input_unregister_device(ft5x06.input); return 0;}/* 传统驱动匹配表 */ static const struct i2c_device_id ft5x06_ts_id[] = { { "edt-ft5206", 0, }, { "edt-ft5426", 0, }, { /* sentinel */ }};/* 设备树匹配表 */static const struct of_device_id ft5x06_of_match[] = { { .compatible = "edt,edt-ft5206", }, { .compatible = "edt,edt-ft5426", }, { /* sentinel */ }};/* i2c驱动结构体 */ static struct i2c_driver ft5x06_ts_driver = { .driver = { .owner = THIS_MODULE, .name = "edt_ft5x06", .of_match_table = of_match_ptr(ft5x06_of_match), }, .id_table = ft5x06_ts_id, .probe = ft5x06_ts_probe, .remove = ft5x06_ts_remove,};/* 驱动入口函数 */static int __init ft5x06_init(void){ int ret = 0; ret = i2c_add_driver(&ft5x06_ts_driver); return ret;}/* 驱动出口函数 */static void __exit ft5x06_exit(void){ i2c_del_driver(&ft5x06_ts_driver);}module_init(ft5x06_init);module_exit(ft5x06_exit);MODULE_LICENSE("GPL"); 2.3 运行测试

多点电容触摸屏测试不需要编写专门的 APP

修改Makefile编译目标变量obj-m := ft5x06.o使用“make -j32”编译出驱动模块文件make -j32 将驱动文件拷贝至“rootfs/lib/modules/4.1.15”中 使用“modprobe”命令加载驱动,加载成功后总线就会进行匹配depmod #第一次加载驱动时,需使用“depmod”命令modprobe ft5x06.ko

当驱动模块加载成功以后会有下图所示信息输入Linux驱动开发|电容触摸屏_linux

驱动加载成功以后就会生成/dev/input/eventX(X=1,2,3…)Linux驱动开发|电容触摸屏_linux_02

使用​​hexdump /dev/input/event2​​命令,查看多点电容触摸屏上报的原始数据:Linux驱动开发|电容触摸屏_驱动开发_03

多点电容触摸屏上报的原始数据表示的含义如下

/* 编号 */ /* tv_sec */ /* tv_usec */ /* type */ /* code */ /* value */0000000 02bb 0000 9459 0007 0003 002f 0000 0000//type为0x3,说明是EV_ABS事件//code为0x2f,为ABS_MT_SLOT,此行是input_mt_slot函数上报的 ABS_MT_SLOT 事件//value=0,说明接下来上报的是第一个触摸点坐标0000010 02bb 0000 9459 0007 0003 0039 0005 0000//type为0x3,说明是EV_ABS事件//code为0x39,为ABS_MT_TRACKING_ID//说明此行是input_mt_report_slot_state函数上报的ABS_MT_TRACKING_ID事件//value=5,说明给 SLOT0 分配的 ID 为 50000020 02bb 0000 9459 0007 0003 0035 03ec 0000//type为0x3,说明是EV_ABS事件//code为0x35,为ABS_MT_POSITION_X//说明此行是input_report_abs函数上报的ABS_MT_POSITION_X事件//value=0x03ec=1004,说明触摸点X轴坐标为1004,属于屏幕右上角区域0000030 02bb 0000 9459 0007 0003 0036 0017 0000//type为0x3,说明是EV_ABS事件//code为0x36,为ABS_MT_POSITION_Y//说明此行是input_report_abs函数上报的ABS_MT_POSITION_Y事件//value=0x17=23,说明Y轴坐标为23,由此可以看出本次触摸的坐标为(1004,23)0000040 02bb 0000 9459 0007 0001 014a 0001 0000//type为0x1,说明是EV_KEY事件,code=0x14a为 BTN_TOUCH,value=0x1触摸屏被按下0000050 02bb 0000 9459 0007 0003 0000 03ec 0000//type为0x3,说明是EV_ABS事件//code为0x0,为ABS_X,用于单点触摸的时候上报X轴坐标//说明此行是input_mt_report_pointer_emulation函数上报的ABS_X事件//value=0x03ec=1004,说明触摸点X轴坐标为1004,属于屏幕右上角区域0000060 02bb 0000 9459 0007 0003 0001 0017 0000//type为0x3,说明是EV_ABS事件//code为0x1,为ABS_Y,用于单点触摸的时候上报y轴坐标//说明此行是input_mt_report_pointer_emulation函数上报的ABS_Y事件//value=0x17=23,说明Y轴坐标为23,由此可以看出本次触摸的坐标为(1004,23)0000070 02bb 0000 9459 0007 0000 0000 0000 0000//type为0x0,说明是EV_SYN事件,由input_sync函数上报0000080 02bb 0000 e5f8 0008 0003 0039 ffff ffff//type为0x3,说明是EV_ABS事件,code为0x39,即ABS_MT_TRACKING_ID//value=0xffffffff=-1,说明触摸点离开了屏幕0000090 02bb 0000 e5f8 0008 0001 014a 0000 0000//type为0x1,说明是EV_KEY事件,code=0x14a为BTN_TOUCH,value=0x0手指离开触摸屏00000a0 02bb 0000 e5f8 0008 0000 0000 0000 0000type为0x0,说明是EV_SYN事件,由input_sync函数上报 2.4 将驱动添加到内核中运行

将触摸驱动编译为模块,每次系统启动以后手动加载驱动模块的方式不是很方便。所以当我们把驱动调试成功以后一般都会将其编译到内核中,这样内核启动以后就会自动加载驱动,不需要再手动 modprobe了。下面将介绍如何将驱动添加到内核中,步骤如下:

将驱动文件放到合适的位置:ft5x06.c是个触摸屏驱动,因此放到内核的drivers/input/touchscreen目录下修改对应的 Makefile:修改drivers/input/touchscreen目录下的Makefile,在末尾添加如下代码obj-y += ft5x06.o重新编译内核,然后用新的 zImage启动开发板。若驱动添加成功,系统启动的时候就会输出如下图所示的信息Linux驱动开发|电容触摸屏_#define_04

触摸屏驱动启动后,会自动生成 /dev/input/evenvtX,使用​​hexdump /dev/input/eventX​​命令,查看触摸屏上报的数据,如坐标数据上报正常,说明驱动工作没问题

另外,还可以通过 tslib 来直观的测试多点电容触摸屏驱动,比观看 eventX 原始数据方便的多,具体请参考​​触摸屏调试库tslib的移植与使用​​一文

Linux驱动开发|电容触摸屏_touchscreen_05



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3