代码示例_触摸屏驱动

 

 


 

 

  1 #include <linux/module.h>
  2 #include <linux/init.h>
  3 #include <linux/input.h>
  4 #include <linux/gpio.h>
  5 #include <linux/interrupt.h>
  6 #include <linux/i2c.h>
  7 #include <linux/slab.h>
  8 #include <linux/delay.h>
  9 
 10 #include <plat/gpio-cfg.h>
 11 
 12 #define TS_MAX_WIDTH 800
 13 #define TS_MAX_HEIGHT 480
 14 
 15 
 16 #define TS_INT_GPIO  S5PV210_GPH1(6)
 17 #define TS_RESET_GPIO  S5PV210_GPD0(3)
 18 
 19 
 20 //设计一个全局的设备对象
 21 struct ts_global{
 22     int irqno;
 23     int flags; // 中断触发方式
 24     struct i2c_client *client; //记录匹配之后的i2c client
 25     struct input_dev *inputdev;
 26 
 27     struct work_struct work; //中断下半部
 28 };
 29 
 30 struct ts_global *gt811_dev;
 31 
 32 
 33 
 34 //重写类似于i2c_master_send()/i2c_master_recv()
 35 int gt811_i2c_send(struct i2c_client *client, char *buf, int count)
 36 {
 37     int ret;
 38     
 39     struct i2c_adapter *adapter = client->adapter;
 40     struct i2c_msg msg;
 41     
 42     msg.addr = client->addr;
 43     msg.flags = 0; //读1还是写0
 44     msg.len = count; 
 45     msg.buf = buf;
 46     //参数1---适配器--来自于i2c client 
 47     //参数2--数据包
 48     //参数3--数据包的个数
 49     //返回值--正确返回消息的个数,错误返回负数
 50     ret = i2c_transfer(adapter, &msg, 1);
 51 
 52     return ret==1?count:ret;
 53     
 54 }
 55 
 56 
 57 // char rbuf[10] = {0x7, 0x21 /*寄存器地址*/,  };  // 后面8个字节用于存放读取到的数据
 58 // gt811_i2c_recv_reg(client , rbuf, 10);
 59 int gt811_i2c_recv_reg(struct i2c_client *client, char *buf, int count)
 60 {
 61     int ret;
 62     
 63     struct i2c_adapter *adapter = client->adapter;
 64     struct i2c_msg msg[2];
 65     
 66     msg[0].addr = client->addr;
 67     msg[0].flags = 0; //先写
 68     msg[0].len = 2;   //寄存器地址为16bit
 69     msg[0].buf = &buf[0];
 70 
 71     msg[1].addr = client->addr;
 72     msg[1].flags = 1; //后读
 73     msg[1].len = count-2;   //
 74     msg[1].buf = &buf[2]; 
 75     
 76     //参数1---适配器--来自于i2c client 
 77     //参数2--数据包
 78     //参数3--数据包的个数
 79     //返回值--正确返回消息的个数,错误返回负数
 80     ret = i2c_transfer(adapter, msg, 2);
 81 
 82     return ret==2?count-2:ret;
 83 
 84 }
 85 
 86 
 87 int gt811_init_reg(void)
 88 {
 89     int ret;
 90     
 91     uint8_t config_info[] = {
 92         0x06,0xA2,   //寄存器地址
 93         
 94         0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0x05,0x55,0x15,0x55,0x25,0x55,\
 95         0x35,0x55,0x45,0x55,0x55,0x55,0x65,0x55,0x75,0x55,0x85,0x55,0x95,0x55,0xA5,0x55,\
 96         0xB5,0x55,0xC5,0x55,0xD5,0x55,0xE5,0x55,0xF5,0x55,0x1B,0x03,0x00,0x00,0x00,0x13,\
 97         0x13,0x13,0x0F,0x0F,0x0A,0x50,0x30,0x0D,0x03,0x00,0x05,0x58,0x02,0x00,0x04,0x00,\
 98         0x00,0x32,0x2C,0x34,0x2E,0x00,0x00,0x04,0x14,0x22,0x04,0x00,0x00,0x00,0x00,0x00,\
 99         0x20,0x14,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x30,\
100         0x25,0x28,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x01\
101     };
102 
103     config_info[57] &= ~(1<<3);
104     gt811_dev->flags = IRQF_TRIGGER_FALLING;
105 
106     config_info[61] = TS_MAX_HEIGHT & 0xff;
107     config_info[62] = TS_MAX_HEIGHT >> 8;
108 
109     config_info[63] = TS_MAX_WIDTH& 0xff;
110     config_info[64] = TS_MAX_WIDTH >> 8;
111     
112     ret = gt811_i2c_send(gt811_dev->client, config_info, ARRAY_SIZE(config_info));
113 
114     return ret>0?0:ret;
115 
116 }
117 
118 
119 
120 void gt811_irq_work(struct work_struct *work)
121 {
122 
123     /*
124         1,通过i2c_tranfser(会导致休眠)读取到坐标
125         2, 分析坐标
126         3, 上报坐标
127 
128     */
129 
130     int ret;
131     uint8_t axis_buf[36] = {0x7, 0x21,};
132     
133     ret = gt811_i2c_recv_reg(gt811_dev->client, axis_buf, 36);
134     if(ret < 0)
135     {
136         printk("gt811_i2c_recv_reg error\n");
137         return;
138     }
139 
140     //先进行校验
141     //先要知道当前是哪几个点
142     unsigned char temp = axis_buf[2] & 0x1f; // 取低5bit
143     int i;
144     unsigned char soft_chksum = 0;
145     int index;
146     switch(temp)
147     {
148         case 0: //没有点,表示抬起
149             index = 4;
150             break;
151         case 1:  //表示第0点被点
152             index = 9;
153             break;
154         case 2: 
155         case 3:  //表示第1点被点
156             index = 14;
157             break;
158 
159         default: //表示 2, 3, 4点
160             index = 35;
161             break;
162 
163     }
164     for(i=2; i<index; i++)
165             soft_chksum += axis_buf[i];
166 
167     if(soft_chksum != axis_buf[index])
168     {
169         printk("check sum error\n");
170         return ;
171     }
172 
173     // 判断出当前有几个点,具体是那几个点
174     temp = axis_buf[2] & 0x1f; // 取低5bit
175     int pcount = 0 ; //点的个数
176     int pset[5]; //当前被点的点号集合
177     for(i=0; i<5; i++)
178     {
179         if(temp & 1)
180         {
181             pset[pcount++]  = i;
182         }
183         temp = temp >> 1;
184     }
185 
186     int j;
187     __u16 x;
188     __u16 y;
189     __u8 p;
190     int pindex = 0;
191     if(pcount > 0)
192     {
193         for(j=0; j<pcount; j++)
194         {
195             switch(pset[j])
196             {
197                 case 0:
198                     pindex = 4;
199                     break;
200                 case 1:
201                     pindex = 9;
202                     break;
203                 case 2:
204                     pindex = 14;
205                     break;
206                 case 3:
207                     pindex = 19;
208                     break;
209                 case 4:
210                     pindex = 30;
211                     break;
212             }
213             if(pset[j] == 3)
214             {
215                 x = axis_buf[19]<<8 | axis_buf[26];
216                 y = axis_buf[27]<<8 | axis_buf[28];
217                 p = axis_buf[29];
218             }else
219             {
220                 x = axis_buf[pindex]<<8 | axis_buf[pindex+1];
221                 y = axis_buf[pindex+2]<<8 | axis_buf[pindex+3];
222                 p = axis_buf[pindex+4];
223             }
224 
225             swap(x, y);
226 
227             y = 480-y;
228             //printk("x = %d, y = %d, p = %d, id = %d\n", x, y, p, pset[j]);
229 
230             input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_X, x);
231             input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_Y, y);
232             input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_PRESSURE, p);
233             input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_TOUCH_MAJOR, p);
234             input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_TRACKING_ID, pset[j]);
235             input_mt_sync(gt811_dev->inputdev);
236             
237         }
238     }
239     //按下和抬起
240     input_report_key(gt811_dev->inputdev, BTN_TOUCH, pcount > 0);
241     input_sync(gt811_dev->inputdev);
242 }
243 
244 
245 irqreturn_t  gt811_irq_svc(int irqno, void *dev_id)
246 {
247 
248 
249     //启动下半部--委托
250     schedule_work(&gt811_dev->work);
251     
252 
253     return IRQ_HANDLED;
254 }
255 
256 
257 
258 int gt811_drv_probe(struct i2c_client *client, const struct i2c_device_id *id)
259 {
260     int ret;
261     
262     gt811_dev = kzalloc(sizeof(struct ts_global), GFP_KERNEL);
263 
264     // 0--记录当前的i2c client
265     gt811_dev->client = client;
266 
267     /*
268     4, 硬件初始化:
269                     a, 初始化寄存器
270                         1, 设置中断引脚为悬浮输入态,RESET设置成GPIO(内部上拉)
271                         2, RESET引脚设置成输出低(开始复位), 延时1ms, 转成输入态
272                         3, 延迟至少20ms,通过i2c寻址gt811  (确认复位是否成功)
273                         4,如果有响应,分一次或者多次初始化寄存器
274                         5,如果没有响应,重复2步骤
275                     b, 申请中断--request_irq(), 还要用中断下半部(tasklet, 工作队列(选择这个))
276                             |
277                             1,通过i2c_tranfser读取到坐标
278                             2, 分析坐标
279                             3, 上报坐标
280     
281     */
282 
283     gpio_request(TS_INT_GPIO, "ts_int");
284     gpio_direction_input(TS_INT_GPIO);
285     gpio_free(TS_INT_GPIO);
286 
287     gpio_request(TS_RESET_GPIO, "ts_reset");
288     s3c_gpio_setpull(TS_RESET_GPIO, S3C_GPIO_PULL_UP);
289     mdelay(2);
290     gpio_direction_output(TS_RESET_GPIO, 0);
291     mdelay(1);
292     gpio_direction_input(TS_RESET_GPIO);
293     gpio_free(TS_RESET_GPIO);
294 
295     mdelay(25);
296     //通过发送数据给gt811, 看看是否成功
297     char test = 1;
298     ret = i2c_master_send(gt811_dev->client, &test, 1);
299     if(ret < 0)
300     {
301         printk("gt811 reset failed or not found\n");
302         kfree(gt811_dev);
303         return ret;
304     }else
305     {
306         printk("gt811 reset ok\n");
307     }
308     
309     ret = gt811_init_reg();
310     if(ret < 0)
311     {
312         printk("gt811_init_reg failed\n");
313         kfree(gt811_dev);
314         return ret;
315     }else
316     {
317         printk("gt811 init  ok\n");
318     }
319 
320     // 4, 硬件初始化,获取到硬件的数据,上报给input handler
321     //申请中断
322     //初始化中断下半部
323     INIT_WORK(&gt811_dev->work,  gt811_irq_work);
324     
325     gt811_dev->irqno = gpio_to_irq(TS_INT_GPIO);
326     ret = request_irq(gt811_dev->irqno, gt811_irq_svc, gt811_dev->flags,
327                             "ts_eint14", NULL);
328 
329     // 1,  构建一个input device 
330     gt811_dev->inputdev = input_allocate_device();
331 
332     //为输入设备提供额外信息--供用户查看--/sys/class/input/eventX/device/..
333     gt811_dev->inputdev->name = "gt811_ts";
334     gt811_dev->inputdev->phys = "goodix/ts/input0";
335     gt811_dev->inputdev->uniq = "goodix/gt811";
336     gt811_dev->inputdev->id.bustype = BUS_I2C;
337     gt811_dev->inputdev->id.vendor = 0xDEAD;
338     gt811_dev->inputdev->id.product = 0x0007;
339     gt811_dev->inputdev->id.version = 0x0001;
340     
341     // 2, 初始化 input device 
342     // 2.1 设置当前输入设备能够产生那些类型数据
343     __set_bit(EV_ABS, gt811_dev->inputdev->evbit);
344     __set_bit(EV_KEY, gt811_dev->inputdev->evbit);
345 
346 
347     // 2.2设置要产生那些按键
348     __set_bit(BTN_TOUCH, gt811_dev->inputdev->keybit);
349     __set_bit(KEY_MENU, gt811_dev->inputdev->keybit);
350     __set_bit(KEY_HOME, gt811_dev->inputdev->keybit);
351     __set_bit(KEY_ESC, gt811_dev->inputdev->keybit);
352 
353 
354     //  2.3 设置要产生那些绝对数据
355     //针对单点
356     __set_bit(ABS_X, gt811_dev->inputdev->absbit);
357     __set_bit(ABS_Y, gt811_dev->inputdev->absbit);
358     __set_bit(ABS_PRESSURE, gt811_dev->inputdev->absbit);
359 
360     //针对多点
361     __set_bit(ABS_MT_POSITION_X, gt811_dev->inputdev->absbit);
362     __set_bit(ABS_MT_POSITION_Y, gt811_dev->inputdev->absbit);
363     __set_bit(ABS_MT_PRESSURE, gt811_dev->inputdev->absbit);
364     __set_bit(ABS_MT_TOUCH_MAJOR, gt811_dev->inputdev->absbit);
365     __set_bit(ABS_MT_TRACKING_ID, gt811_dev->inputdev->absbit);
366     
367 
368     // 2.4 --如果有abs的值,还需要设置abs的最大值和最小值
369     //参数1---设置哪个设备
370     //参数2--坐标
371     //参数3-4;最小值和最大值
372     //参数5-6: 一般填0
373     input_set_abs_params(gt811_dev->inputdev, ABS_X, 0, TS_MAX_WIDTH, 0, 0);
374     input_set_abs_params(gt811_dev->inputdev, ABS_Y, 0, TS_MAX_HEIGHT, 0, 0);
375     input_set_abs_params(gt811_dev->inputdev, ABS_PRESSURE, 0, 16, 0, 0);
376 
377     input_set_abs_params(gt811_dev->inputdev, ABS_MT_POSITION_X, 0, TS_MAX_WIDTH, 0, 0);
378     input_set_abs_params(gt811_dev->inputdev, ABS_MT_POSITION_Y, 0, TS_MAX_HEIGHT, 0, 0);
379     input_set_abs_params(gt811_dev->inputdev, ABS_MT_PRESSURE, 0, 16, 0, 0);
380     input_set_abs_params(gt811_dev->inputdev, ABS_MT_TOUCH_MAJOR, 0, 16, 0, 0);
381     input_set_abs_params(gt811_dev->inputdev, ABS_MT_TRACKING_ID, 0, 4, 0, 0);
382     
383     // 3, 注册input device 
384     ret = input_register_device(gt811_dev->inputdev);
385 
386 
387     
388     
389     
390     
391 
392     return 0;
393 
394 }
395 
396 
397 int gt811_drv_remove(struct i2c_client *client)
398 {
399     
400     input_unregister_device(gt811_dev->inputdev);
401     input_free_device(gt811_dev->inputdev);
402 
403     cancel_work_sync(&gt811_dev->work);
404     free_irq(gt811_dev->irqno, NULL);
405     
406     kfree(gt811_dev);
407 
408     return 0;
409 }
410 
411 
412 const struct i2c_device_id  gt811_id_table[] = {
413         {"gt811_i2c_ts", 0x811},
414         {}
415 };
416 
417 
418 struct i2c_driver gt811_i2c_drv = {
419     .probe = gt811_drv_probe,
420     .remove = gt811_drv_remove,
421     .driver = {
422         .name = "gt811_drv",
423     },
424     .id_table = gt811_id_table,
425 
426 };
427 
428 
429 
430 
431 static int __init gt811_drv_init(void)
432 {
433     //注册一个i2c driver
434     return i2c_add_driver(&gt811_i2c_drv);
435 
436 }
437 
438 
439 static void __exit gt811_drv_exit(void)
440 {
441     
442     i2c_del_driver(&gt811_i2c_drv);
443 }
444 
445 module_init(gt811_drv_init);
446 module_exit(gt811_drv_exit);
447 MODULE_LICENSE("GPL");

 

 


 

 

 1 CROSS_COMPILE = arm-none-linux-gnueabi-
 2 CC = $(CROSS_COMPILE)gcc
 3 
 4 #指定内核源码路径
 5 KERNEL_DIR = /home/kernel/linux-3.0.8
 6 CUR_DIR = $(shell pwd)
 7 
 8 MYAPP = ts_app
 9 
10 MODULE = gt811_i2c_drv
11 
12 all:
13     #让make进入内核源码编译,同时将当前目录中的c程序作为内核模块一起编译
14     make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
15 ifneq ($(MYAPP), )    
16     $(CC)  -o $(MYAPP) $(MYAPP).c
17 endif
18 
19 clean:
20     #删除上面编译生成的文件
21     make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
22     rm -rf $(MYAPP)
23 
24 install:
25     cp *.ko $(MYAPP) /opt/rootfs/drv_module
26 
27 #指定当前目录下哪个文件作为内核模块编
28 obj-m += $(MODULE).o

 

 

 

 

 


 

 

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <sys/types.h>
 6 #include <sys/stat.h>
 7 #include <fcntl.h>
 8 #include <sys/ioctl.h>
 9 #include <linux/input.h>
10 
11 
12 int main(void)
13 {
14 
15     int fd;
16     int ret;
17 
18     struct input_event package;
19 
20  
21     fd = open("/dev/event0",O_RDWR);
22     if(fd < 0)
23     {
24         perror("open");
25         exit(1);
26     }
27 
28     while(1)
29     {
30         bzero(&package,sizeof(package));
31         ret = read(fd, &package,sizeof(package));
32         if(ret < 0)
33         {
34             perror("read");
35             exit(1);
36         }
37         //拆包
38         if(package.type == EV_KEY)
39         {
40             if(package.code == KEY_DOWN)
41             {
42                 if(package.value)
43                 {
44                     printf("<app>-- KEY_DOWN pressed\n");
45                 }else
46                 {
47                     printf("<app>-- KEY_DOWN up\n");
48                 }
49             }
50             if(package.code == KEY_POWER)
51             {
52                 if(package.value)
53                 {
54                     printf("<app>-- KEY_POWER pressed\n");
55                 }else
56                 {
57                     printf("<app>-- KEY_POWER up\n");
58                 }
59             }
60         }
61 
62 
63         if(package.type == EV_ABS)
64         {
65             switch(package.code)
66             {
67                 case ABS_MT_POSITION_X:
68                     printf(" x = %d ", package.value);
69                     break;
70                 case ABS_MT_POSITION_Y:
71                     printf(" y = %d ", package.value);
72                     break;
73                 case ABS_MT_PRESSURE:
74                     printf(" p = %d ", package.value);
75                     break;
76                 case ABS_MT_TRACKING_ID:
77                     printf(" id = %d \n", package.value);
78                     break;
79 
80             }
81         }
82     }
83 
84     close(fd);
85     
86     return 0;
87 }

 

posted @ 2019-06-09 13:12  panda_w  阅读(837)  评论(0编辑  收藏  举报