struct tmouchscreen{ struct i2c_client*client; 。。。 。。。 }

编辑:www.fx114.net
本篇文章主要介绍了"gt82x.c",主要涉及到gt82x.c方面的内容,对于gt82x.c感兴趣的同学可以参考一下。
/*---------------------------------------------------------------------------------------------------------
* driver/input/touchscreen/goodix_touch.c
* Copyright(c) 2010 Goodix Technology Corp.
* 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.
* GNU General Public License for more details.
* Change Date:
, add point_queue's definiens.
, rewrite point_queue's definiens.
, delete point_queue for Android 2.2/Android 2.3 and so on.
*---------------------------------------------------------------------------------------------------------*/
#include &linux/i2c.h&
#include &linux/input.h&
#include &goodix_touch.h&
#include &linux/interrupt.h&
#include &linux/delay.h&
#include &linux/interrupt.h&
#include &linux/errno.h&
#include &linux/kernel.h&
#include &linux/module.h&
#include &linux/slab.h&
#include &linux/init.h&
#include &linux/ioport.h&
#include &asm/irq.h&
#include &asm/io.h&
#include &mach/irqs.h&
#include &mach/system.h&
#include &mach/hardware.h&
#include &mach/gpio.h&
#include &linux/ctp.h&
#include &linux/pm.h&
#ifdef CONFIG_HAS_EARLYSUSPEND
#include &linux/earlysuspend.h&
#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_PM)
#include &linux/pm.h&
#define FOR_TSLIB_TEST
#define TEST_I2C_TRANSFER
#ifndef GUITAR_GT80X
#error The code does not match the hardware version.
extern struct ctp_config_info config_
//分配触摸屏结构内核空间;
struct goodix_ts_data {
int panel_
uint8_t bad_
char phys[32];
struct i2c_client *
struct input_dev *input_
uint8_t use_
//用户中断标志位;
uint8_t use_
//关屏标志位;
uint32_t gpio_
uint32_t gpio_
uint32_t screen_
uint32_t screen_
struct ts_event
struct work_
int (*power)(struct goodix_ts_data * ts, int on);
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_
const char *f3x_ts_name = &gt82x&;
static struct workqueue_struct *goodix_
#define X_DIFF (800)
static u32 debug_mask = 0;
#define dprintk(level_mask,fmt,arg...)
if(unlikely(5 & level_mask)) \
printk(&***CTP***&fmt, ## arg)
#define CTP_IRQ_NUMBER
(config_info.irq_gpio_number)
#define CTP_IRQ_MODE
(TRIG_EDGE_NEGATIVE)
#define CTP_NAME
#define SCREEN_MAX_X
(screen_max_x)
#define SCREEN_MAX_Y
(screen_max_y)
#define PRESS_MAX
#define READ_TOUCH_ADDR_H
#define READ_TOUCH_ADDR_L
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;
/* Addresses to scan */
static const unsigned short normal_i2c[2] = {0x5d,I2C_CLIENT_END};
static const int chip_id_value[3] = {0x13,0x27,0x28};
static uint8_t read_chip_value[3] = {0x0f,0x7d,0};
/*used by GT80X-IAP module */
struct i2c_client * i2c_connect_client = NULL;
static void goodix_init_events(struct work_struct *work);
static void goodix_resume_events(struct work_struct *work);
struct workqueue_struct *goodix_init_
struct workqueue_struct *goodix_resume_
//通过如下宏可以创建一个要
推后的完成
static DECLARE_WORK(goodix_init_work, goodix_init_events);
static DECLARE_WORK(goodix_resume_work, goodix_resume_events);
struct goodix_ts_data *ts_
/*******************************************************
Read data from the i2c slave device.
client: i2c device.
buf[0]:operate address.
buf[1]~buf[len]:read data buffer.
len:operate length.
numbers of i2c_msgs to transfer
*********************************************************/
static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, uint16_t len)
struct i2c_msg msgs[2];
int ret=-1;
//发送写地址
msgs[0].flags = !I2C_M_RD;
msgs[0].addr = client-&
msgs[0].len = 2;
//data address
msgs[0].buf =
//接收数据
msgs[1].flags = I2C_M_RD;//读消息
msgs[1].addr = client-&
msgs[1].len = len-2;
msgs[1].buf = buf+2;
ret=i2c_transfer(client-&adapter, msgs, 2);
/*******************************************************
write data to the i2c slave device.
client: i2c device.
buf[0]:operate address.
buf[1]~buf[len]:write data buffer.
len:operate length.
numbers of i2c_msgs to transfer.
*********************************************************/
//i2c写功能函数 参数(i2c_client结构体,包含设备地址等信息;需要写的数据,需要写的寄存器起始地址+需要写的数据;数据长度)
static int i2c_write_bytes(struct i2c_client *client, uint8_t *data, uint16_t len)
struct i2c_
int ret=-1;
msg.flags = !I2C_M_RD;//写消息
msg.addr = client-&
ret=i2c_transfer(client-&adapter, &msg,1);
/*******************************************************
write i2c end cmd.
ts: client Private data structures
Successful returns 1
*******************************************************/
static s32 i2c_end_cmd(struct goodix_ts_data *ts)
u8 end_cmd_data[2]={0x80, 0x00};
ret=i2c_write_bytes(ts-&client,end_cmd_data,2);
/*******************************************************
Foundation
i2c communication test
ts:i2c client structure
Successful :1 fail:0
*******************************************************/
//Test i2c to check device. Before it SHUTDOWN port Must be low state 30ms or more.
//通过写地址,测试i2c是否能正常通信;
static bool goodix_i2c_test(struct i2c_client * client)
uint8_t test_data[1] = { 0 }; //only write a data address.
for(retry=0; retry & 5; retry++)
ret =i2c_write_bytes(client, test_data, 1); //Test i2c.
if (ret == 1)
msleep(5);
return ret==1 ? true :
* ctp_detect - Device detection callback for automatic device creation
* return value:
//读取设备IC的chip_id
static int ctp_detect(struct i2c_client *client, struct i2c_board_info *info)
struct i2c_adapter *adapter = client-&
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)){
printk(&======return=====\n&);
return -ENODEV;
if(twi_id == adapter-&nr){
i2c_read_bytes(client,read_chip_value,3);
dprintk(DEBUG_INIT,&addr:0x%x,chip_id_value:0x%x\n&,client-&addr,read_chip_value[2]);
while(chip_id_value[i++]){
if(read_chip_value[2] == chip_id_value[i - 1]){
strlcpy(info-&type, CTP_NAME, I2C_NAME_SIZE);
printk(&%s:I2C connection might be something wrong ! \n&,__func__);
return -ENODEV;
return -ENODEV;
/*******************************************************
GTP initialize function.
ts: i2c client private struct.
Executive outcomes.1---succeed.
*******************************************************/
//芯片初始化,对点位置的初始化,影响触摸效果;
static int goodix_init_panel(struct goodix_ts_data *ts)
int ret=-1;
int i = 0;
uint8_t config_info1[114];
//触摸芯片寄存器初始化;FAE
uint8_t data_info0[] = {
0x0F,0x80,
0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,
0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,
0x0A,0x19,0x0B,0x1A,0xFF,0x15,0x16,0x17,
0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x03,0x0D,
0x04,0x0E,0x05,0x0F,0x06,0x10,0x07,0x11,
0x08,0x12,0xFF,0x0D,0xFF,0x0F,0x10,0x11,
0x12,0x13,0x0F,0x03,0x10,0x88,0x88,0x20,
0x00,0x00,0x06,0x00,0x00,0x02,0x50,0x3C,
0x35,0x03,0x00,0x05,0x00,0x03,0x20,0x05,
0x00,0x5A,0x5A,0x46,0x46,0x08,0x00,0x03,
0x19,0x05,0x14,0x10,0x00,0x07,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01
uint8_t data_info1[] = {
0x0F,0x80,
0x00,0x0F,0x01,0x10,0x02,0x11,0x03,0x12,
0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,
0x08,0x17,0x09,0x18,0x0A,0x19,0x0B,0x1A,
0x0C,0x1B,0x0D,0x1C,0x0E,0x1D,0x13,0x09,
0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,
0x0E,0x04,0x0D,0x03,0x0C,0x02,0x0B,0x01,
0x0A,0x00,0x0B,0x03,0x10,0x00,0x00,0x2C,
0x00,0x00,0x03,0x00,0x00,0x02,0x40,0x30,
0x60,0x03,0x00,0x05,0x00,0x03,0x20,0x05,
0x00,0x66,0x4E,0x60,0x49,0x06,0x00,0x23,
0x19,0x05,0x14,0x10,0x03,0xFC,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
dprintk(DEBUG_OTHERS_INFO,&init panel\n&);
if(read_chip_value[2] == 0x13) {
//i2c地址检测;
ret=i2c_write_bytes(ts-&client,data_info0, 114);
}else if(read_chip_value[2] == 0x28){ //828
ret=i2c_write_bytes(ts-&client,data_info1, 114);
i2c_end_cmd(ts);
msleep(10);
dprintk(DEBUG_OTHERS_INFO,&init panel ret = %d\n&,ret);
if (ret & 0)
msleep(100);
config_info1[0] = 0x0F;
config_info1[1] = 0x80;
ret=i2c_read_bytes(ts-&client,config_info1,114);
for( i = 0;i&114;i++){
dprintk(DEBUG_OTHERS_INFO,&i = %d config_info1[i] = %x \n&,i,config_info1[i]);
msleep(10);
static s32 goodix_ts_version(struct goodix_ts_data *ts)
u8 buf[8];
buf[0] = 0x0f;
buf[1] = 0x7d;
i2c_read_bytes(ts-&client, buf, 5);
i2c_end_cmd(ts);
dprintk(DEBUG_INIT,&PID:%02x, VID:%02x%02x\n&, buf[2], buf[3], buf[4]);
/*******************************************************
Touch down report function.
ts:private data.
id:tracking id.
x:input x.
y:input y.
w:input weight.
*******************************************************/
//上报函数;
static void goodix_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)
dprintk(DEBUG_X_Y_INFO,&source data:ID:%d, X:%d, Y:%d, W:%d\n&, id, x, y, w);
if(1 == exchange_x_y_flag){
swap(x, y);
if(1 == revert_x_flag){
x = SCREEN_MAX_X -
if(1 == revert_y_flag){
y = SCREEN_MAX_Y -
dprintk(DEBUG_X_Y_INFO,&report data:ID:%d, X:%d, Y:%d, W:%d\n&, id, x, y, w);
//上报函数;
input_report_abs(ts-&input_dev, ABS_MT_POSITION_X, x);
input_report_abs(ts-&input_dev, ABS_MT_POSITION_Y, y);
input_report_abs(ts-&input_dev, ABS_MT_TOUCH_MAJOR, w);
input_report_abs(ts-&input_dev, ABS_MT_WIDTH_MAJOR, w);
input_report_abs(ts-&input_dev, ABS_MT_TRACKING_ID, id);
//上报多点坐标值时多点同步信号
input_mt_sync(ts-&input_dev);
//集合报点;每波每个点上报后就mt_sync,当这波所有的点结束了,再使用input_sync进行同步;
/*******************************************************
Touch up report function.
ts:private data.
*******************************************************/
static void goodix_touch_up(struct goodix_ts_data* ts)
input_report_abs(ts-&input_dev, ABS_MT_TOUCH_MAJOR, 0);
input_report_abs(ts-&input_dev, ABS_MT_WIDTH_MAJOR, 0);
input_mt_sync(ts-&input_dev);
//计算上报坐标值;核心函数;坐标点的计算.上报和多点处理;
static void goodix_ts_work_func(struct work_struct *work)
u8* coor_data = NULL;
point_data[2 + 2 + 5 * MAX_FINGER_NUM + 1]={READ_TOUCH_ADDR_H,READ_TOUCH_ADDR_L};
check_sum = 0;
touch_num = 0;
finger = 0;
key_value = 0;
s32 input_x = 0;
s32 input_y = 0;
s32 input_w = 0;
s32 idx = 0;
s32 ret = -1;
struct goodix_ts_data *ts = NULL;
dprintk(DEBUG_X_Y_INFO,&===enter %s===\n&,__func__);
ts = container_of(work, struct goodix_ts_data, work);
//读取触摸屏值,手指数坐标值等;
ret = i2c_read_bytes(ts-&client, point_data, 10);
finger = point_data[2];
//按下手指数;
touch_num = (finger & 0x01) + !!(finger & 0x02) + !!(finger & 0x04) + !!(finger & 0x08) + !!(finger & 0x10);
if (touch_num & 1){
u8 buf[25];
buf[0] = READ_TOUCH_ADDR_H;
buf[1] = READ_TOUCH_ADDR_L + 8;
ret = i2c_read_bytes(ts-&client, buf, 5 * (touch_num - 1) + 2);
memcpy(&point_data[10], &buf[2], 5 * (touch_num - 1));
i2c_end_cmd(ts);
if (ret &= 0){
printk(&%s:I2C read error!&,__func__);
goto exit_work_
if((finger & 0xC0) != 0x80){
dprintk(DEBUG_INIT,&%s:Data not ready!&,__func__);
goto exit_work_
key_value = point_data[3]&0x0f; // 1, 2, 4, 8
if ((key_value & 0x0f) == 0x0f){
if (!goodix_init_panel(ts)){
printk(&%s:Reload config failed!\n&,__func__);
goto exit_work_
coor_data = &point_data[4];
//计算坐标值;
check_sum = 0;
for ( idx = 0; idx & 5 * touch_ idx++){
check_sum += coor_data[idx];
if (check_sum != coor_data[5 * touch_num]){
printk(&%s:Check sum error!&,__func__);
goto exit_work_
//读取坐标值上报;
if (touch_num){
s32 pos = 0;
//根据手指数,循环读取;
for (idx = 0; idx & MAX_FINGER_NUM; idx++){
if (!(finger & (0x01 && idx))){
//读取x的值;
= coor_data[pos] && 8;
input_x |= coor_data[pos + 1];
= coor_data[pos + 2] && 8;
input_y |= coor_data[pos + 3];
= coor_data[pos + 4];
//上报函数;input_mt_sync单点同步;
goodix_touch_down(ts, idx, input_x, input_y, input_w);
dprintk(DEBUG_X_Y_INFO,&Touch Release!&);
goodix_touch_up(ts);
#if GTP_HAVE_TOUCH_KEY
//依据变量touching的值确定触点个数,报告点击事件与相关数据
for (idx= 0; idx & GTP_MAX_KEY_NUM; idx++){
input_report_key(ts-&input_dev, touch_key_array[idx], key_value & (0x01&&idx));
//同步多点值;上报坐标值结束时的同步信号
//input_report_key(ts-&input_dev, BTN_TOUCH, (touch_num || key_value));
input_sync(ts-&input_dev);
exit_work_func:
//中断执行函数;
static u32 goodix_ts_irq_hanbler(struct goodix_ts_data *ts)
dprintk(DEBUG_INT_INFO,&==========------TS Interrupt-----============\n&);
//中断执行;
//wq:由create_singlethread_workqueue函数获得;在te_init中,创建工作队列和工作线程,初始化创建线程;
//ts-&work:在probe中,INIT_WORK中增加goodix_ts_work_func任务;
//中断函数触发后,执行中断函数goodix_ts_irq_hanbler,中断函数里面对队列调度,调用goodix_ts_work_func
queue_work(goodix_wq, &ts-&work);
//初始化管理;
static int goodix_ts_power(struct goodix_ts_data * ts, int on)
s32 ret = -1;
s32 success = 1;
u8 i2c_control_buf1[3] = {0x0F,0xF2,0xc0};
//suspend cmd
u8 i2c_control_buf2[3] = {0x0F,0xF2,0x00};
switch(on)
ret = i2c_write_bytes(ts-&client, i2c_control_buf1, 3);
i2c_end_cmd(ts);
// ctp_wakeup(int status,int ms)操作wakeup(reset)引脚,
当ms 不为0 时,表示将wakeup(reset)引脚设置为status
状态ms 时间,wakeup(reset)引脚的正常工作状态应该为(!Status)。当ms 为0 时,表示
将wakeup(reset) 设置为status 状态。该引脚默认设置为输出功能。
ctp_wakeup(0,100);
if(STANDBY_WITH_POWER_OFF == standby_level){
//i2c检测;
ret = goodix_i2c_test(ts-&client);
printk(&Warnning: I2C connection might be something wrong!\n&);
ctp_wakeup(0,50);
ret = goodix_i2c_test(ts-&client);
printk(&retry fail!\n&);
return -1;
pr_info(&===== goodix i2c test ok=======\n&);
//初始化寄存器等;
ret = goodix_init_panel(ts);
if( ret != 1){
printk(&init panel fail!\n&);
return -1;
ret = i2c_write_bytes(ts-&client, i2c_control_buf2, 3);
msleep(10);
printk(&%s: Cant't support this command.&,f3x_ts_name );
return -EINVAL;
static void goodix_resume_events (struct work_struct *work)
u8 i2c_control_buf[3] = {0x0F,0xF2,0x00};
if (ts_init-&is_suspended == false) {
ctp_wakeup(0,2);
ret = i2c_write_bytes(ts_init-&client, i2c_control_buf, 3);
if( ret != 1){
printk(&set active mode fail!\n&);
msleep(10);
} else if (ts_init-&power) {
ret = ts_init-&power(ts_init, 1);
if (ret & 0)
dprintk(DEBUG_SUSPEND,&%s power on failed\n&, f3x_ts_name);
sw_gpio_eint_set_enable(CTP_IRQ_NUMBER,1);
//停用设备
static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg)
struct goodix_ts_data *ts = i2c_get_clientdata(client);
dprintk(DEBUG_SUSPEND,&CONFIG_PM:enter earlysuspend: goodix_ts_suspend. \n&);
#ifndef CONFIG_HAS_EARLYSUSPEND
ts-&is_suspended =
if (ts-&is_suspended == true) {
flush_workqueue(goodix_resume_wq);
sw_gpio_eint_set_enable(CTP_IRQ_NUMBER,0);
ret = cancel_work_sync(&ts-&work);
flush_workqueue(goodix_wq);
if (ts-&power) {
ret = ts-&power(ts,0);
if (ret & 0)
dprintk(DEBUG_SUSPEND,&%s power off failed\n&, f3x_ts_name);
return 0 ;
//重新唤醒
static int goodix_ts_resume(struct i2c_client *client)
//获取设备client的设备驱动私有数据;
struct goodix_ts_data *ts = i2c_get_clientdata(client);
dprintk(DEBUG_SUSPEND,&CONFIG_PM:enter laterresume: goodix_ts_resume. \n&);
ts-&is_suspended =
queue_work(goodix_resume_wq, &goodix_resume_work);
#ifdef CONFIG_HAS_EARLYSUSPEND
//停用设备
static void goodix_ts_early_suspend(struct early_suspend *h)
struct goodix_ts_data *ts = container_of(h, struct goodix_ts_data, early_suspend);
dprintk(DEBUG_SUSPEND,&CONFIG_HAS_EARLYSUSPEND:enter earlysuspend: goodix_ts_suspend. \n&);
ts-&is_suspended =
flush_workqueue(goodix_resume_wq);
sw_gpio_eint_set_enable(CTP_IRQ_NUMBER,0);
ret = cancel_work_sync(&ts-&work);
flush_workqueue(goodix_wq);
if (ts-&power) {
ret = ts-&power(ts,0);
if (ret & 0)
dprintk(DEBUG_SUSPEND,&%s power off failed\n&, f3x_ts_name);
//重新唤醒
static void goodix_ts_late_resume(struct early_suspend *h)
struct goodix_ts_data *ts = container_of(h, struct goodix_ts_data, early_suspend);
dprintk(DEBUG_SUSPEND,&CONFIG_HAS_EARLYSUSPEND:enter laterresume: goodix_ts_resume. \n&);
if (ts-&is_suspended == false)
queue_work(goodix_resume_wq, &goodix_resume_work);
printk(&ts-&is_suspended:%d\n&,ts-&is_suspended);
//初始化函数;DECLARE_WORK
static void goodix_init_events (struct work_struct *work)
int ret = 0;
ctp_wakeup(0,100);
// 触摸芯片初始化; //触摸芯片寄存器初始化
ret = goodix_init_panel(ts_init);
if(!ret) {
printk(&init panel fail!\n&);
dprintk(DEBUG_INIT,&init panel succeed!\n&);
//int_handle中断申请句柄
//申请中断;中断号,中断模式(上升沿触发,下降沿触发....),goodix_ts_irq_hanbler中断执行函数;
int_handle = sw_gpio_irq_request(CTP_IRQ_NUMBER,CTP_IRQ_MODE,(peint_handle)goodix_ts_irq_hanbler,ts_init);
if (!int_handle) {
pr_info( &goodix_probe: request irq failed\n&);
//if(!ctp_set_int_port_rate(1))
//printk(&CTP set gpio clk 24M fail!\n&);
/*******************************************************
触摸屏探测函数
在注册驱动时调用(要求存在对应的client);
用于IO,中断等资源申请;设备注册;触摸屏初始化等工作
client:待驱动的设备结构体
id:设备ID
执行结果码,0表示正常执行
********************************************************/
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct goodix_ts_data *
int ret = 0;
dprintk(DEBUG_INIT,&=============GT82x Probe==================\n&);
if (!i2c_check_functionality(client-&adapter, I2C_FUNC_I2C)){
dev_err(&client-&dev, &System need I2C function.\n&);
ret = -ENODEV;
goto err_check_functionality_
//分配触摸屏结构的内核空间;
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (ts == NULL) {
ret = -ENOMEM;
goto err_alloc_data_
i2c_connect_client =
//used by Guitar Updating.
//初始化工作队列,这个中断触发后调用队列中的goodix_ts_work_func函数,计算上报坐标值;
INIT_WORK(&ts-&work, goodix_ts_work_func);
//goodix_ts_work_func该函数初始化了触摸芯片;goodix_init_panel
ts-&client =
//将设备驱动的私有数据连接到设备client中
i2c_set_clientdata(ts-&client, ts);
//分配input驱动内核空间;申请input_dev结构
ts-&input_dev = input_allocate_device();
if (ts-&input_dev == NULL)
ret = -ENOMEM;
dev_dbg(&client-&dev,&Failed to allocate input device\n&);
goto err_input_dev_alloc_
//input初始化参数设定,我们在前面提到Linux和Android多点触摸协议里面有对这部分说明;
ts-&input_dev-&evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
//probe函数调用此函数给设备的input_dev结构体初始化;
//该参数会在Android的EventHub.cpp中被读取;
#ifndef GOODIX_MULTI_TOUCH
ts-&input_dev-&keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
ts-&input_dev-&absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
//设置屏幕大小参数;
input_set_abs_params(ts-&input_dev, ABS_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(ts-&input_dev, ABS_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(ts-&input_dev, ABS_PRESSURE, 0, 255, 0, 0);
//ABS_MT_TRACKING_ID用来支持硬件跟踪多点信息,即该点属于哪一条线等
ts-&input_dev-&absbit[0] = BIT_MASK(ABS_MT_TRACKING_ID) |
BIT_MASK(ABS_MT_TOUCH_MAJOR)| BIT_MASK(ABS_MT_WIDTH_MAJOR) |
BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y);
// for android
input_set_abs_params(ts-&input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(ts-&input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(ts-&input_dev, ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(ts-&input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(ts-&input_dev, ABS_MT_TRACKING_ID, 0, MAX_FINGER_NUM, 0, 0);
#ifdef FOR_TSLIB_TEST
//set_bit设置事件;触摸屏坐标键值属性;
set_bit(BTN_TOUCH, ts-&input_dev-&keybit);
//触摸屏版本信息设定;该部分信息可以通过cat /proc/bus/input/devices 看到;
sprintf(ts-&phys, &input/goodix-ts&);
ts-&input_dev-&name = CTP_NAME;
ts-&input_dev-&phys = ts-&
ts-&input_dev-&id.bustype = BUS_I2C;
ts-&input_dev-&id.vendor = 0xDEAD;
ts-&input_dev-&id.product = 0xBEEF;
ts-&input_dev-&id.version = 0x1105;
ts-&is_suspended =
//注册输入设备;对于input子系统来说,这个就是重头戏了;只有注册了input子系统,其他的才有作用;
//注册输入设备,并和对应的handler处理函数挂钩
ret = input_register_device(ts-&input_dev);
if (ret) {
dev_err(&client-&dev,&Unable to register %s input device\n&, ts-&input_dev-&name);
goto err_input_register_device_
goodix_wq = create_singlethread_workqueue(&goodix_wq&);
if (!goodix_wq) {
printk(KERN_ALERT &Creat %s workqueue failed.\n&, f3x_ts_name);
return -ENOMEM;
flush_workqueue(goodix_wq);
//ts_power里面init初始化了;
ts-&power = goodix_ts_
goodix_init_wq = create_singlethread_workqueue(&goodix_init&);
if (goodix_init_wq == NULL) {
printk(&create goodix_wq fail!\n&);
return -ENOMEM;
goodix_resume_wq = create_singlethread_workqueue(&goodix_resume&);
if (goodix_resume_wq == NULL) {
printk(&create goodix_resume_wq fail!\n&);
return -ENOMEM;
queue_work(goodix_init_wq, &goodix_init_work);
#ifdef CONFIG_HAS_EARLYSUSPEND
//对睡眠唤醒操作;
ts-&early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
ts-&early_suspend.suspend = goodix_ts_early_
ts-&early_suspend.resume= goodix_ts_late_
register_early_suspend(&ts-&early_suspend);
goodix_ts_version(ts);
dprintk(DEBUG_INIT,&========Probe Ok================\n&);
err_input_register_device_failed:
input_free_device(ts-&input_dev);
err_input_dev_alloc_failed:
i2c_set_clientdata(client, NULL);
err_alloc_data_failed:
err_check_functionality_failed:
/*******************************************************
驱动资源释放
client:设备结构体
执行结果码,0表示正常执行
********************************************************/
static int goodix_ts_remove(struct i2c_client *client)
struct goodix_ts_data *ts = i2c_get_clientdata(client);
dev_notice(&client-&dev,&The driver is removing...\n&);
//free_irq(SW_INT_IRQNO_PIO, ts);
sw_gpio_irq_free(int_handle);
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&ts-&early_suspend);
cancel_work_sync(&goodix_init_work);
cancel_work_sync(&goodix_resume_work);
flush_workqueue(goodix_wq);
if (goodix_resume_wq)
destroy_workqueue(goodix_resume_wq);
if (goodix_init_wq)
destroy_workqueue(goodix_init_wq);
if (goodix_wq)
destroy_workqueue(goodix_wq);
input_unregister_device(ts-&input_dev);
input_free_device(ts-&input_dev);
i2c_set_clientdata(ts-&client, NULL);
kfree(ts);
//可用于该驱动的 设备名—设备ID 列表
//only one client
static const struct i2c_device_id goodix_ts_id[] = {
{ CTP_NAME, 0 },
//设备驱动结构体
static struct i2c_driver goodix_ts_driver = {
.class = I2C_CLASS_HWMON,
= goodix_ts_probe,
= goodix_ts_remove,
.id_table = goodix_ts_id,
goodix_ts_suspend,
goodix_ts_resume,
.driver = {
.name = CTP_NAME,
.owner = THIS_MODULE,
//i2c地址;
.address_list = normal_i2c,
//从sys_config里面获取system_
static int ctp_get_system_config(void)
ctp_print_info(config_info,DEBUG_INIT);
twi_id = config_info.twi_
screen_max_x = config_info.screen_max_x;
screen_max_y = config_info.screen_max_y;
revert_x_flag = config_info.revert_x_
revert_y_flag = config_info.revert_y_
exchange_x_y_flag = config_info.exchange_x_y_
if((twi_id == 0) || (screen_max_x == 0) || (screen_max_y == 0)){
printk(&%s:read config error!\n&,__func__);
//驱动加载函数
static int __devinit goodix_ts_init(void)
int ret = -1;
//int err = -1;
dprintk(DEBUG_INIT,&****************************************************************\n&);
if(config_info.ctp_used == 0){
printk(&*** ctp_used set to 0 !\n&);
printk(&*** if use ctp,please put the sys_config.fex ctp_used set to 1. \n&);
if(!ctp_get_system_config()){
printk(&%s:read config fail!\n&,__func__);
ctp_wakeup(0,2);
goodix_ts_driver.detect = ctp_
//通过I2C核心的i2c_add_driver函数添加i2c_driver使用到的关键数据结构为i2c_driver,
//注意i2c_driver中使用的name需要与input_dev name一致
ret = i2c_add_driver(&goodix_ts_driver);
dprintk(DEBUG_INIT,&****************************************************************\n&);
//驱动卸载函数
static void __exit goodix_ts_exit(void)
i2c_del_driver(&goodix_ts_driver);
ctp_free_platform_resource();
late_initcall(goodix_ts_init);
module_exit(goodix_ts_exit);
module_param_named(debug_mask,debug_mask,int,S_IRUGO | S_IWUSR | S_IWGRP);
MODULE_DESCRIPTION(&Goodix Touchscreen Driver&);
MODULE_LICENSE(&GPL v2&);
本文标题:
本页链接:

我要回帖

更多关于 struct tm 的文章

 

随机推荐