touch key gt216驱动架构记录

    xiaoxiao2021-03-25  26

    /* drivers/input/touchscreen/gt216_ts.c * * FocalTech TouchScreen driver in android 4.x. * * Copyright (c) 2010 Focal tech Ltd. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include <linux/i2c.h> #include <linux/input.h> #include <linux/earlysuspend.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <mach/irqs.h> #include <linux/kernel.h> #include <linux/semaphore.h> #include <linux/mutex.h> #include <linux/module.h> #include <linux/init-input.h> #include <linux/syscalls.h> #include <linux/unistd.h> #include <linux/uaccess.h> #include <linux/fs.h> #include <linux/string.h> #include <linux/timer.h> #include <linux/input/mt.h> #include <linux/io.h> #include <mach/sys_config.h> #include <mach/gpio.h> #include <linux/clk.h> #include <linux/gpio.h> #include <linux/input-polldev.h> #include "gt216_ts.h" struct ts_event { u16 au16_x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */ u16 au16_y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */ u8 au8_touch_event[CFG_MAX_TOUCH_POINTS]; /*touch event: 0 -- down; 1-- contact; 2 -- contact */ u8 au8_finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */ u16 pressure; u8 touch_point; }; struct gt216_ts_data { unsigned int irq; unsigned int x_max; unsigned int y_max; u32 irq_handle; struct work_struct pen_event_work; struct workqueue_struct *ts_workqueue; struct i2c_client *client; struct input_dev *input_dev; struct ts_event event; struct gt216_platform_data *pdata; #ifdef CONFIG_PM struct early_suspend *early_suspend; #endif }; static struct ctp_config_info config_info = { .input_type = CTP_TYPE, }; static int screen_max_x = 0; static int screen_max_y = 0; static int revert_x_flag = 0; static int revert_y_flag = 0; static int exchange_x_y_flag = 0; static u32 int_handle = 0; static __u32 twi_id = 0; static int int_number = 0; static u32 wakeup_number = 0; static bool is_suspend = false; static struct i2c_client *this_client; static struct gt216_ts_data *gt216_ts; static void i2c_button_poll(struct input_polled_dev *poll_dev); static int get_button_value(char *keyValue); static char get_button_code(char *keyValue); char button_code_config[12] = { KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6, KEY_7,KEY_8,KEY_9,KEY_A,KEY_B }; #define FTS_CTL_IIC /* *gt216_i2c_Read-read data and write data by i2c *@client: handle of i2c *@writebuf: Data that will be written to the slave *@writelen: How many bytes to write *@readbuf: Where to store data read from slave *@readlen: How many bytes to read * *Returns negative errno, else the number of messages executed * * */ #if 1 int gt216_i2c_Read( char *writebuf, int writelen, char *readbuf, int readlen) { int ret; if (writelen > 0) { struct i2c_msg msgs[] = { { .addr = this_client->addr, .flags = 0, .len = writelen, .buf = writebuf, }, { .addr = this_client->addr, .flags = I2C_M_RD, .len = readlen, .buf = readbuf, }, }; ret = i2c_transfer(this_client->adapter, msgs, 2); if (ret < 0) dev_err(&this_client->dev, "%s:i2c read error.\n", __func__); } else { struct i2c_msg msgs[] = { { .addr = this_client->addr, .flags = I2C_M_RD, .len = readlen, .buf = readbuf, }, }; ret = i2c_transfer(this_client->adapter, msgs, 1); if (ret < 0) dev_err(&this_client->dev, "%s:i2c read error.\n", __func__); } return ret; } /*write data by i2c*/ int gt216_i2c_Write( char *writebuf, int writelen) { int ret; struct i2c_msg msg[] = { { .addr = this_client->addr, .flags = 0, .len = writelen, .buf = writebuf, }, }; ret = i2c_transfer(this_client->adapter, msg, 1); if (ret < 0) dev_err(&this_client->dev, "%s i2c write error.\n", __func__); //printk("%s:i2c write error----mrzhang.\n", __func__); return ret; } #if 0 /*release the point*/ static void gt216_ts_release(struct gt216_ts_data *data) { input_mt_sync(data->input_dev); input_sync(data->input_dev); } #endif /*Read touch point information when the interrupt is asserted.*/ static int initGT216(void) { int ret; unsigned char set1[] = {0x06, 0x10}; //禁止组合键,禁止PWM,电平中断模式,idle时间0ms 0x04-> 2 4 del #if 0 //0x10-0x1f寄存器,对应各通道灵敏度,范围0x02-0x3f,0x02灵敏度最高,0x3f灵敏度最低 unsigned char set2[] = {0x10, 0x05,0x11, 0x07,0x12, 0x07,0x13, 0x0a,0x14, 0x0a,0x15,0x08,0x16, \ 0x08,0x17, 0x09,0x18, 0x09,0x19, 0x08,0x1a, 0x08,0x1b, 0x04,0x1c, 0x3f, \ 0x1d, 0x3f,0x1e, 0x3f,0x1f, 0x3f}; #else //灵敏度调低点,以防外部干扰导致死机 /*unsigned char set2[] = {0x10, 0x06, 0x08, 0x08, 0x0b, 0x0b, 0x09, 0x09, 0x0a, \ 0x0a, 0x09, 0x03, 0x08, 0x3f, 0x3f, 0x3f, 0x3f};*/ unsigned char set2[] = {0x10, 0x04, 0x05, 0x05, 0x05, 0x04, 0x05, 0x07, 0x05, \ 0x05, 0x07, 0x03, 0x03, 0x3f, 0x3f, 0x3f, 0x3f}; #endif unsigned char set3[] = {0x01,0x01}; //rstGT216(); char reg = 0x01; char value = 0; ret = gt216_i2c_Write( set1, sizeof(set1) ); if(ret < 0) return -1; ret = gt216_i2c_Write( set2, sizeof(set2) ); if(ret < 0) return -1; return 0; } /*The gt216 device will signal the host about TRIGGER_FALLING. *Processed when the interrupt is asserted. */ static int ctp_get_system_config(void) { twi_id = config_info.twi_id; int_number = config_info.int_number; wakeup_number = config_info.wakeup_number; printk("int_number = %d wakeup_number = %d\n",int_number,wakeup_number); return 1; } static int get_button_value(char *keyValue) { static char down_flag = 0; static char up_flag = 0; static char interrupt_state = 0; char writeReg[3] = {0x01,0x02,0x03}; char readKeyValue[2] = {0}; char readInterruptState = 0; static char key_store[2]; if( 0 > gt216_i2c_Read(&writeReg[0],1,&readInterruptState,1)) return KEY_ERRO; if(readInterruptState&0x01 == 0x01){ up_flag = 0; if (interrupt_state == 0&&++down_flag>=6){ down_flag = 0; interrupt_state = 1; if( 0 > gt216_i2c_Read(&writeReg[1],1,&readKeyValue[0],1)) return KEY_ERRO; if( 0 > gt216_i2c_Read(&writeReg[2],1,&readKeyValue[1],1)) return KEY_ERRO; if(readKeyValue[0]||readKeyValue[1]){ key_store[0] = keyValue[0] = readKeyValue[0]; key_store[1] = keyValue[1] = readKeyValue[1]; return KEY_DOWN; }else { keyValue[0] = key_store[0] ; keyValue[1] = key_store[1] ; return KEY_UP ; } } }else { down_flag = 0; if (interrupt_state == 1&&++up_flag>=6){ up_flag = 0; interrupt_state = 0; if( 0 > gt216_i2c_Read(&writeReg[1],1,&readKeyValue[0],1)) return KEY_ERRO; if( 0 > gt216_i2c_Read(&writeReg[2],1,&readKeyValue[1],1)) return KEY_ERRO; if(readKeyValue[0]||readKeyValue[1]){ key_store[0] = keyValue[0] = readKeyValue[0]; key_store[1] = keyValue[1] = readKeyValue[1]; return KEY_DOWN; }else { keyValue[0] = key_store[0] ; keyValue[1] = key_store[1] ; return KEY_UP ; } } } return KEY_ERRO; } static char get_button_code(char *keyValue) { int i; int value = keyValue[0]|keyValue[1]<<8; printk("value = 0x%x 0x%x 0x%x\n ",value,keyValue[0],keyValue[1]<<8); for(i = 0; i <16;i++) { if(value & (1<<i)) { printk("i=%d \n",i); return button_code_config[i]; } } return -1; } static void i2c_button_poll(struct input_polled_dev *poll_dev) { char keyValue[2] = {0}; switch(get_button_value(keyValue)){ case KEY_DOWN: input_report_key(poll_dev->input,get_button_code(keyValue),1); input_sync(poll_dev->input); printk("code : %d down\n",get_button_code(keyValue)); break; case KEY_UP: input_report_key(poll_dev->input,get_button_code(keyValue),0); input_sync(poll_dev->input); printk("code : %d up\n",get_button_code(keyValue)); break; } } struct gt216_platform_data gt216_padta; static int reg_get(){ int i; char wbuff[16] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}; char rbuff=0x0; for(i=0;i<16;i++){ if( 0 > gt216_i2c_Read(&wbuff[i],1,&rbuff,1)) return -1; printk("addr = 0x%x value=0x%x\n",wbuff[i],rbuff); rbuff=0x0; } return 0; } static int gt216_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct gt216_platform_data *pdata = >216_padta; //struct input_dev *input_dev; struct input_polled_dev *input_poll_dev; int err = 0,ret = 0; printk("**********gt216_ts_probe************\n"); printk("client.adapter.timeout = %d\n",(client->adapter)->timeout); client->irq = gpio_to_irq(int_number); printk("client->irq =%d\n",client->irq); gt216_padta.reset = wakeup_number; #if 1 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { err = -ENODEV; goto exit_check_functionality_failed; } gt216_ts = kzalloc(sizeof(struct gt216_ts_data), GFP_KERNEL); if (!gt216_ts) { err = -ENOMEM; goto exit_alloc_data_failed; } this_client = client; gt216_ts->client = client; gt216_ts->pdata = pdata; i2c_set_clientdata(client, gt216_ts); input_poll_dev = input_allocate_polled_device(); if(!input_poll_dev) return -1; input_poll_dev->poll = i2c_button_poll; input_poll_dev->poll_interval = 10; //10ms #endif gt216_ts->input_dev = input_poll_dev->input; int i; __set_bit(EV_KEY, gt216_ts->input_dev->evbit); for( i = 0; i< sizeof(button_code_config)/sizeof(button_code_config[0]);i++) { __set_bit(button_code_config[i], gt216_ts->input_dev->keybit); } __set_bit(INPUT_PROP_DIRECT, gt216_ts->input_dev->propbit); gt216_ts->input_dev->name = GT216_NAME; err = input_register_polled_device(input_poll_dev); if (err) { dev_err(&client->dev, "gt216_ts_probe: failed to register input device: %s\n", dev_name(&client->dev)); goto exit_input_register_device_failed; } /*make sure CTP already finish startup process */ msleep(150); while (0 > initGT216()) { printk("gt216 init fail\n"); msleep(100); } printk("gt216 init ok\n"); int rg = reg_get(); if(rg)printk("reg_get err \n"); return 0; exit_input_register_device_failed: input_free_device(gt216_ts->input_dev); #ifdef CONFIG_PM exit_request_reset: gpio_free(gt216_ts->pdata->reset); #endif exit_irq_request_failed: i2c_set_clientdata(client, NULL); kfree(gt216_ts); exit_create_singlethread: kfree(gt216_ts); exit_alloc_data_failed: exit_check_functionality_failed: return err; #endif } #ifdef CONFIG_PM static void gt216_ts_suspend(struct early_suspend *handler) { struct gt216_ts_data *ts = i2c_get_clientdata(this_client); dev_dbg(&ts->client->dev, "[FTS]gt216 suspend\n"); disable_irq(ts->irq); } static void gt216_ts_resume(struct early_suspend *handler) { struct gt216_ts_data *ts = i2c_get_clientdata(this_client); dev_dbg(&ts->client->dev, "[FTS]gt216 resume.\n"); ctp_wakeup(config_info.wakeup_number, 0, 20); enable_irq(ts->irq); } #else #define gt216_ts_suspend NULL #define gt216_ts_resume NULL #endif static int __devexit gt216_ts_remove(struct i2c_client *client) { struct gt216_ts_data *gt216_ts; gt216_ts = i2c_get_clientdata(this_client); input_unregister_device(gt216_ts->input_dev); #ifdef CONFIG_PM gpio_free(gt216_ts->pdata->reset); #endif sw_gpio_irq_free(gt216_ts->irq_handle); kfree(gt216_ts); i2c_set_clientdata(this_client, NULL); return 0; } static int i2c_driver_gt216_detect(struct i2c_client *client, struct i2c_board_info *info) { struct i2c_adapter *adapter = client->adapter; int ret; printk("****************client->adapter = %d*******************\n",client->adapter->nr); if(twi_id == adapter->nr) { printk("%s: addr = %x\n", __func__, client->addr); ret = i2c_test(client); if(!ret){ printk("%s:I2C connection might be something wrong \n", __func__); return -ENODEV; } const char *type_name = GT216_NAME; strlcpy(info->type, type_name, I2C_NAME_SIZE); return 0; }else { return -ENODEV; } } static const struct i2c_device_id gt216_ts_id[] = { {GT216_NAME, 0}, {} }; MODULE_DEVICE_TABLE(i2c, gt216_ts_id); static const unsigned short normal_i2c[] = {0x58, I2C_CLIENT_END}; static struct i2c_driver gt216_ts_driver = { .class = I2C_CLASS_HWMON, .probe = gt216_ts_probe, .remove = __devexit_p(gt216_ts_remove), .id_table = gt216_ts_id, .suspend = gt216_ts_suspend, .resume = gt216_ts_resume, .driver = { .name = GT216_NAME, .owner = THIS_MODULE, }, .address_list = normal_i2c, }; static int __init gt216_ts_init(void) { int ret; printk("***********gt216_ts_init*************~~~~~~~~~~~~~~~~\n"); if (input_fetch_sysconfig_para(&(config_info.input_type))) { printk("%s: ctp_fetch_sysconfig_para err.\n", __func__); return 0; } else { ret = input_init_platform_resource(&(config_info.input_type)); if (0 != ret) { printk("%s:ctp_ops.init_platform_resource err. \n", __func__); } } ctp_get_system_config(); ctp_wakeup(config_info.wakeup_number, 0, 20); gt216_ts_driver.detect = i2c_driver_gt216_detect, ret = i2c_add_driver(>216_ts_driver); if (ret) { printk(KERN_WARNING "Adding gt216 driver failed " "(errno = %d)\n", ret); } else { pr_info("Successfully added driver %s\n", gt216_ts_driver.driver.name); } return ret; } static void __exit gt216_ts_exit(void) { i2c_del_driver(>216_ts_driver); } module_init(gt216_ts_init); module_exit(gt216_ts_exit); MODULE_AUTHOR("<luowj>"); MODULE_DESCRIPTION("FocalTech TouchScreen driver"); MODULE_LICENSE("GPL"); 头文件: #ifndef __LINUX_gt216_TS_H__ #define __LINUX_gt216_TS_H__ /* -- dirver configure -- */ #define CFG_MAX_TOUCH_POINTS 2 #define PRESS_MAX 0xFF #define FT_PRESS 0x08 #define GT216_NAME "gt216" #define KEY_ERRO  -1 #define KEY_DOWN  0 #define KEY_UP    1  /*register address*/ #define gt216_REG_FW_VER 0xA6 #define gt216_REG_POINT_RATE 0x88 #define gt216_REG_THGROUP 0x80 int gt216_i2c_Read(char *writebuf, int writelen,    char *readbuf, int readlen); int gt216_i2c_Write(char *writebuf, int writelen); /* The platform data for the Focaltech gt216 touchscreen driver */ struct gt216_platform_data { unsigned int x_max; unsigned int y_max; unsigned long irqflags; /*default:IRQF_TRIGGER_FALLING*/ unsigned int irq; unsigned int reset; }; #endif
    转载请注明原文地址: https://ju.6miu.com/read-299996.html

    最新回复(0)