本文共 10640 字,大约阅读时间需要 35 分钟。
安装完以下ft5x06触摸驱动会打印一下内容,说明驱动编写成功
[12727.015690] ft5x06_driver_init[12727.015821] this is ft5x06_probe ft5x06_device_node is ft5x06[12727.015963] ft5x06_irp_gpio is 52[12727.015973] ft5x06_reset_gpio is 41[12727.027780] input: ft5x06_input_test as /devices/virtual/input/input16[12727.029412] i2c_add_driver is success
输入 cat /proc/bus/input/devices 后成功看到如下:name和代码中的要匹配, input 和打印中的要匹配
I: Bus=0000 Vendor=0000 Product=0000 Version=0000N: Name="ft5x06_input_test"P: Phys=S: Sysfs=/devices/virtual/input/input16U: Uniq=H: Handlers=event7 cpufreqB: PROP=0B: EV=bB: KEY=400 0 0 0 0 1000000B: ABS=1000003
busybox hexdump /dev/input/event7
Event types | code | value | value | |||||
---|---|---|---|---|---|---|---|---|
0000000 | ea4e | 609b | 5f3c | 000c | 0001 | 014a | 0001 | 0000 |
0000010 | ea4e | 609b | 5f3c | 000c | 0003 | 0000 | 0176 | 0000 |
0000020 | ea4e | 609b | 5f3c | 000c | 0003 | 0001 | 0270 | 0000 |
0000030 | ea4e | 609b | 5f3c | 000c | 0000 | 0000 | 0000 | 0000 |
0000040 | ea4e | 609b | ddd3 | 000c | 0001 | 014a | 0000 | 0000 |
0000050 | ea4e | 609b | ddd3 | 000c | 0000 | 0000 | 0000 | 0000 |
#include//这个头文件中/* * Event types */#define EV_SYN 0x00#define EV_KEY 0x01#define EV_REL 0x02#define EV_ABS 0x03#define EV_MSC 0x04#define EV_SW 0x05#define EV_LED 0x11#define EV_SND 0x12#define EV_REP 0x14#define EV_FF 0x15#define EV_PWR 0x16#define EV_FF_STATUS 0x17#define EV_MAX 0x1f#define EV_CNT (EV_MAX+1)/* Code 255 is reserved for special needs of AT keyboard driver */#define BTN_DIGI 0x140#define BTN_TOOL_PEN 0x140#define BTN_TOOL_RUBBER 0x141#define BTN_TOOL_BRUSH 0x142#define BTN_TOOL_PENCIL 0x143#define BTN_TOOL_AIRBRUSH 0x144#define BTN_TOOL_FINGER 0x145#define BTN_TOOL_MOUSE 0x146#define BTN_TOOL_LENS 0x147#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */#define BTN_TOUCH 0x14a#define BTN_STYLUS 0x14b#define BTN_STYLUS2 0x14c#define BTN_TOOL_DOUBLETAP 0x14d#define BTN_TOOL_TRIPLETAP 0x14e#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad *//* * Absolute axes 绝对区域 */#define ABS_X 0x00#define ABS_Y 0x01#define ABS_Z 0x02#define ABS_RX 0x03#define ABS_RY 0x04#define ABS_RZ 0x05#define ABS_THROTTLE 0x06#define ABS_RUDDER 0x07#define ABS_WHEEL 0x08#define ABS_GAS 0x09#define ABS_BRAKE 0x0a#define ABS_HAT0X 0x10#define ABS_HAT0Y 0x11#define ABS_HAT1X 0x12#define ABS_HAT1Y 0x13#define ABS_HAT2X 0x14#define ABS_HAT2Y 0x15#define ABS_HAT3X 0x16#define ABS_HAT3Y 0x17#define ABS_PRESSURE 0x18#define ABS_DISTANCE 0x19#define ABS_TILT_X 0x1a#define ABS_TILT_Y 0x1b#define ABS_TOOL_WIDTH 0x1c#define ABS_VOLUME 0x20#define ABS_MISC 0x28#define ABS_MT_SLOT 0x2f /* MT slot being modified */#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 /* Center X touch position */#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */#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 /* Unique ID of initiated contact */#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 */#define ABS_MAX 0x3f#define ABS_CNT (ABS_MAX+1)
ABS_MT_TRACKING_ID
参数是类型B特有的。实际上,每个slot会和一个ID相对应,一个非负数的表示一次接触,-1表示这是一个无用的slot(或者理解为一次接触的结束)。无论在接触的类型相对应的slot发生了改变,驱动都应该通过改变这个值来使这个slot失效。并且下一次触摸的ID值会是这次的值加1。
EV_ABS
事件的一种类型。表示绝对坐标。
EV_KEY
事件的一种类型。表示是按键事件。
BTN_TOUCH
触碰按键。其值是DOWN或者UP。
BTN_TOOL_FINGER
按键的是finger,并且其值也是DOWN或者UP。
ABS_MT_POSITION_X,ABS_MT_POSITION_Y
相对于屏幕中心的x,y坐标。
ABS_MT_TOUCH_MAJOR
接触部分的长轴长度。相当于椭圆的长轴。
ABS_MT_TOUCH_MINOR
接触部分的短轴长度。相当于椭圆的短轴。
EV_SYN
事件类型的一种。在事件完成的时候更新数据。
SYN_REPORT
可以看到,在一次触摸中,就有好几次SYN_REPORT。是因为有很多的事件,或者是说SYN_REPORT就是一次事件的结束。上报内核
第一行
Event types 0001 代表 EV_KEY
code 014a 代表 #define BTN_TOUCH 0x14a 是touch 事件 0代表抬起, 1 代表摁下
value 0001 对应的是摁下
第一行 这个事件的意思是 单个手指触摸到了屏幕
第二行
Event types 0003 代表#define EV_ABS 0x03 是触摸的绝对坐标
code 0000 代表 #define ABS_X 0x00 是x轴的绝对坐标
value 0176 换算十进制 是 374
第二行的 这个事件的意思是 单个手指 触摸屏幕的x的坐标是 374
第三行
Event types 0003 代表#define EV_ABS 0x03 是触摸的绝对坐标
code 0001 代表 #define ABS_Y 0x00 是y轴的绝对坐标
value 0270 换算十进制 是624
这个事件的意思是 单个手指 触摸屏幕的y的绝对坐标 是624
第四行
Event types 0000 代表 #define EV_SYN 0x00 是上报这个事件信号
将摁下,触摸屏幕的点的坐标 上报给了内核
第五行
Event types 0001 代表 EV_KEY
code 014a 代表 #define BTN_TOUCH 0x14a 是touch 事件 0代表抬起, 1 代表摁下
value 0000 对应的是抬起
这个事件意思是 单个手指离开了屏幕
第六行
Event types 0000 代表 #define EV_SYN 0x00 是上报这个事件信号
将摁下,触摸屏幕的点的坐标 上报给了内核
代码
#include#include #include #include #include #include #include #include #include #include //工作模式为正常状态的地址#define DEVICE_MOOE 0x00//为工作时的地址#define ID_G_MODE 0xa4struct device_node *ftx06_device_node;struct input_dev *ft5x06_dev;static void ft5x06_fun(struct work_struct *work);DECLARE_WORK(ft5x06_work,ft5x06_fun);static struct i2c_client * ft5x06_client;int irq;static void ft5x06_write_reg(u8 reg_addr, u8 data, u8 len);static void ft5x06_write_reg(u8 reg_addr, u8 data, u8 len){ u8 buff[256]; struct i2c_msg msgs[] = { [0] = { .addr = ft5x06_client->addr, .flags = 0, .len = len + 1, .buf = buff, }, // [1] = { // .addr = ft5x06_client->addr, // .flags = 1, // .len = sizeof(data), // .buf = &data, // } }; buff[0] = reg_addr; memcpy(&buff[1], &data, len); i2c_transfer(ft5x06_client->adapter, msgs, 1);}struct of_device_id ft5x06_id[] = { {.compatible = "edt,ft5x0x_ts", 0}, {.compatible = "edt,ft5x0x_ts", 0}, {.compatible = "edt,ft5x0x_ts", 0}, {}};struct i2c_device_id ft5x06_id_ts[] = { {"xxxxx", 0}, {},};static int ft5x06_read_reg(u8 reg_addr);static int ft5x06_read_reg(u8 reg_addr){ u8 data; struct i2c_msg msgs[] = { [0] = { .addr = ft5x06_client->addr, .flags = 0, .len = sizeof(reg_addr), .buf = ®_addr, }, [1] = { .addr = ft5x06_client->addr, .flags = 1, .len = sizeof(data), .buf = &data, } }; i2c_transfer(ft5x06_client->adapter, msgs, 2); return data;}static void ft5x06_fun(struct work_struct *work){ int TOUCH1_XH, TOUCH1_XL,x; int TOUCH1_YH, TOUCH1_YL,y; int TD_STATUS; //读取TOUCH1_XH 寄存器的值 TOUCH1_XH = ft5x06_read_reg(0x03); //读取TOUCH1_XL 寄存器的值 TOUCH1_XL = ft5x06_read_reg(0x04); //获取x的坐标值 x = ((TOUCH1_XH << 8) | TOUCH1_XL) & 0x0fff; //读取TOUCH1_YH 寄存器的值 TOUCH1_YH = ft5x06_read_reg(0x05); //读取TOUCH1_YL 寄存器的值 TOUCH1_YL = ft5x06_read_reg(0x06); //获取Y的坐标值 y = ((TOUCH1_YH << 8) | TOUCH1_YL) & 0x0fff; //读取寄存器TD_STATUS 的值 TD_STATUS = ft5x06_read_reg(0x02); //获取有没有手指在屏幕上 TD_STATUS = TD_STATUS & 0xf; //判断有没有手指按上,如果有的话就要上报摁下的事件,没有就要上报抬手的事件 if (TD_STATUS ==0) { input_report_key(ft5x06_dev, BTN_TOUCH, 0); input_sync(ft5x06_dev); } else { input_report_key(ft5x06_dev, BTN_TOUCH, 1); input_report_abs(ft5x06_dev, ABS_X, x); input_report_abs(ft5x06_dev, ABS_Y, y); input_sync(ft5x06_dev); } }irq_handler_t ft5x06_handler(int irq, void * args){ schedule_work(&ft5x06_work); return IRQ_HANDLED;}int ft5x06_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id){ int ret; int ft5x06_irp_gpio; int ft5x06_reset_gpio; printk("this is ft5x06_probe \n "); ft5x06_client = i2c_client;//因为我们要在别的函数里面用到这个client,所以我们要把他们复制进来 ftx06_device_node = of_find_node_by_path("/i2c@ff110000/ft5x06@38"); //获得触摸芯片的节点 if (ftx06_device_node == NULL) { printk("of_find_node_by_path is error \n"); return -1; } printk("ft5x06_device_node is %s \n", ftx06_device_node->name); //获得中断号 ft5x06_irp_gpio = of_get_named_gpio(ftx06_device_node, "touch-gpio", 0); if (ft5x06_irp_gpio < 0) { printk("of_get_named_gpio_irq is error \n"); return -1; } //获得复位引脚标号 ft5x06_reset_gpio = of_get_named_gpio(ftx06_device_node, "reset-gpios", 0); if (ft5x06_reset_gpio < 0) { printk("of_get_named_gpio_reset is error \n"); return -1; } printk("ft5x06_irp_gpio is %d \n", ft5x06_irp_gpio); printk("ft5x06_reset_gpio is %d \n", ft5x06_reset_gpio); //申请中断引脚 gpio_free(ft5x06_irp_gpio); ret = gpio_request(ft5x06_irp_gpio, "irq_gpio"); if (ret < 0 ) { printk("gpio_request_irp is error \n "); return -1; } //申请复位引脚 gpio_free(ft5x06_reset_gpio); ret = gpio_request(ft5x06_reset_gpio, "reset_gpio"); if (ret < 0 ) { printk("gpio_request_reset is error \n "); return -1; } //把中断的引脚设置为输入 gpio_direction_input(ft5x06_irp_gpio); //设置复位引脚的方向为输出,然后停止复位 gpio_direction_output(ft5x06_reset_gpio, 0); msleep(5); gpio_set_value(ft5x06_reset_gpio, 1); irq = gpio_to_irq(ft5x06_irp_gpio); ret = request_irq(irq, ft5x06_handler, IRQ_TYPE_EDGE_FALLING|IRQF_TRIGGER_RISING, "ft5x06_irq", NULL); if (ret < 0) { printk("request_irq is error \n"); goto error_request_irq; } //设置工作模式为正常 ft5x06_write_reg(DEVICE_MOOE, 0, 1); // ret = ft5x06_read_reg(ID_G_MODE, 1, 1); ft5x06_write_reg(ID_G_MODE, 1, 1); ft5x06_dev = input_allocate_device(); ft5x06_dev->name = "ft5x06_input_test"; //key 事件 __set_bit(EV_KEY,ft5x06_dev->evbit); //绝对事件 触摸 __set_bit(EV_ABS, ft5x06_dev->evbit); //支持按键检测 事件 __set_bit(BTN_TOUCH,ft5x06_dev->keybit); //支持x坐标值的范围 __set_bit(ABS_X, ft5x06_dev->absbit); //支持y坐标值的范围 __set_bit(ABS_Y, ft5x06_dev->absbit); //支持压力值的检测 __set_bit(ABS_PRESSURE, ft5x06_dev->keybit); //设置x坐标的范围 input_set_abs_params(ft5x06_dev, ABS_X, 0, 800, 0, 0); //设置y坐标的范围 input_set_abs_params(ft5x06_dev, ABS_Y, 0, 1280, 0, 0); //设置按压范围 input_set_abs_params(ft5x06_dev, ABS_PRESSURE, 0, 255, 0, 0); ret = input_register_device(ft5x06_dev); if (ret < 0) { printk("input_register_device is error \n"); goto error_input_register; } return 0;error_request_irq: free_irq(irq, NULL); return ret;error_input_register: free_irq(irq, NULL); input_unregister_device(ft5x06_dev); input_free_device(ft5x06_dev); return ret;}int ft5x06_remove(struct i2c_client *i2c_client){ printk("ft5x06_remove \n "); return 0;}static struct i2c_driver ft5x06_driver = { .probe = ft5x06_probe, .remove = ft5x06_remove, .id_table = ft5x06_id_ts, .driver = { .owner = THIS_MODULE, .name = "ft5x06_test", .of_match_table = ft5x06_id, },};static int ft5x06_driver_init(void){ int ret; printk("ft5x06_driver_init \n"); ret = i2c_add_driver(&ft5x06_driver); if (ret < 0) { printk("i2c_add_driver is error \n "); return ret ; } printk("i2c_add_driver is success \n"); return 0;}static void ft5x06_driver_exit(void){ printk("ft5x06_driver_exit \n"); input_unregister_device(ft5x06_dev); input_free_device(ft5x06_dev); free_irq(irq, NULL); i2c_del_driver(&ft5x06_driver);}module_init(ft5x06_driver_init);module_exit(ft5x06_driver_exit);MODULE_LICENSE("GPL");
转载地址:http://alrkf.baihongyu.com/