• 代码示例_触摸屏驱动



      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
    ");
    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
    ");
    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
    ", 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
    ");
    302         kfree(gt811_dev);
    303         return ret;
    304     }else
    305     {
    306         printk("gt811 reset ok
    ");
    307     }
    308     
    309     ret = gt811_init_reg();
    310     if(ret < 0)
    311     {
    312         printk("gt811_init_reg failed
    ");
    313         kfree(gt811_dev);
    314         return ret;
    315     }else
    316     {
    317         printk("gt811 init  ok
    ");
    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
    ");
    45                 }else
    46                 {
    47                     printf("<app>-- KEY_DOWN up
    ");
    48                 }
    49             }
    50             if(package.code == KEY_POWER)
    51             {
    52                 if(package.value)
    53                 {
    54                     printf("<app>-- KEY_POWER pressed
    ");
    55                 }else
    56                 {
    57                     printf("<app>-- KEY_POWER up
    ");
    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 
    ", package.value);
    78                     break;
    79 
    80             }
    81         }
    82     }
    83 
    84     close(fd);
    85     
    86     return 0;
    87 }
    Stay hungry, stay foolish 待续。。。
  • 相关阅读:
    vue中element-ui的内置过渡动画
    vue路由自动加载、按组件异步载入vuex以及dll优化
    h5春节小游戏制作
    python脚本通过adb命令安装包
    pipeline
    python闭包与装饰器
    linux-awk
    CSAPP Lab3: The Attack Lab
    CSAPP Lab4 Cache Lab
    HDU. 2243. 考研路茫茫——单词情结(AC自动机 DP 矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/panda-w/p/10949993.html
Copyright © 2020-2023  润新知