touch key gt216驱动架构记录

/* 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
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值