代码示例_触摸屏驱动
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(>811_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(>811_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(>811_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(>811_i2c_drv); 435 436 } 437 438 439 static void __exit gt811_drv_exit(void) 440 { 441 442 i2c_del_driver(>811_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 }
Stay hungry, stay foolish
待续。。。