S5PV210 Android 触摸按键驱动解析
16lz
2021-01-23
/*--------------------------------------------------------------------------------------------------------- * driver/input/touchscreen/goodix_touch.c * * Copyright(c) 2010 Goodix Technology Corp. * Author: Eltonny * Date: 2010.11.11 * *---------------------------------------------------------------------------------------------------------*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/time.h>#include <linux/delay.h>#define DEBUG 1#include <linux/device.h>#include <linux/earlysuspend.h>#include <linux/platform_device.h>#include <linux/hrtimer.h>#include <linux/i2c.h>#include <linux/input.h>#include <linux/interrupt.h>#include <linux/io.h>#include <linux/irq.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#include <linux/gpio.h>#include <linux/ioc4.h>#include <linux/io.h>#include <mach/ut210_gpio_reg.h>#include "goodix_touch.h"#include "goodix_queue.h"#ifndef GUITAR_GT80X#error The code does not match the hardware version.#endif#define GOODIX_DEBUG_F#ifdef GOODIX_DEBUG_F#define GOODIXTS_DEBUG(fmt,args...) printk( "[goodix_ts]: " fmt, ## args) //printk( KERN_DEBUG "[egalax_i2c]: " fmt, ## args)#define DBG() printk("[%s]:%d => \n",__FUNCTION__,__LINE__)#else#define GOODIXTS_DEBUG(fmt,args...) do{ }while(0)#define DBG() do{ }while(0)#endif#ifdef utv210static volatile VIC_REG *VICREG; static volatile UT210_GPIO_REG *UT210_GPIOREG; //denis_wei add 2010-12-08#define TIMER //采用的是定时器扫描的方式#ifdef EINT29 //如果是定义EINT29表示采用的是中断的方式 是对中断的定义 #define EINT_KEY (IRQ_RTC_TIC)//按键中断#define KEY_EINT_EN do { VICREG->VICINTENABLE |= (0x1<<29); \ VICREG->VICINTENCLEAR &= (~(0x1<<29));}while(0)#define KEY_EINT_DIS do {VICREG->VICINTENABLE &= (~(0x1<<29));\ VICREG->VICINTENCLEAR |= (0x1<<29); } while(0) static void goodix_key_callback(struct work_struct *work);static DECLARE_WORK(key_work, goodix_key_callback);static struct input_dev * s_input_dev = NULL;#endif/***wangyulu******/#define MAX_BUTTON_CNT 3static int goodix_scancode[MAX_BUTTON_CNT] = {0x1A,0x1B,0x1C};static int goodix_keycode[MAX_BUTTON_CNT] = {KEY_BACK, KEY_HOME,KEY_MENU};static int goodix_scancode_history[MAX_BUTTON_CNT] = {0,0,0,0};///wangyulu lock_key time#ifdef TIMER //对定时器的定义#define KEY_DETECT_INTERVAL (msecs_to_jiffies(60))//定时60msstatic struct timer_list key_timer;static void lockkey_timer_callback(struct work_struct *work);static DECLARE_WORK(lock_work, lockkey_timer_callback);static struct input_dev * s_input_dev = NULL;static void goodix_key_timer_handler(unsigned long data);#endif#endif#define MID706_SP static struct point_queue finger_list; //record the fingers list /*************************************************/static struct i2c_client * i2c_connect_client = NULL;#ifdef CONFIG_HAS_EARLYSUSPENDstatic void goodix_ts_early_suspend(struct early_suspend *h);static void goodix_ts_late_resume(struct early_suspend *h);#endif#define GOODIX_KEY_I2C (0xC4>>1)//触摸按键芯片的设备地址 /*Function as i2c_master_send */static int i2c_write_key(struct i2c_client *client,uint8_t *data,int len){ struct i2c_msg msg; int ret=-1; //发送设备地址 msg.flags=!I2C_M_RD;//写消息 msg.addr=GOODIX_KEY_I2C; msg.len=len; msg.buf=data; ret=i2c_transfer(i2c_get_adapter(1),&msg,1); return ret;}//************ urbetter+ ******************static int goodix_i2c_rxdata(char *rxdata, int length){ int ret; struct i2c_msg msgs[] = { { .addr = GOODIX_KEY_I2C, .flags = 0, .len = 1, .buf = rxdata, }, { .addr = GOODIX_KEY_I2C, .flags = I2C_M_RD, .len = length, .buf = rxdata, }, }; ret = i2c_transfer(i2c_get_adapter(1), msgs, 2);//i2c_get_adapter(1)选着iic 1 if (ret < 0) pr_err("msg %s i2c read error: %d\n", __func__, ret); return ret;}#ifdef TIMER ////轮询处理函数wangyulustatic void goodix_key_timer_handler(unsigned long data){ //ceshi schedule_work(&lock_work); mod_timer(&key_timer,jiffies + KEY_DETECT_INTERVAL);}/////lock_key的处理函数 key_703 wangyulustatic void lockkey_timer_callback(struct work_struct *work){ int i; int boy_flag = 0; unsigned char buf[2]; buf[0] = 0xc5; goodix_i2c_rxdata(buf, 1); //printk("key_TIMER=0x%02X\n", buf[0]); //没有按下是0xff boy for(i = 0; i < MAX_BUTTON_CNT; i++) { if((buf[0] == goodix_scancode_history[i]) || (buf[0] == goodix_scancode[i])) { printk("key_TIMER=0x%02X\n", buf[0]); //没有按下是0xff boy goodix_scancode_history[i]= buf[0]; input_report_key(s_input_dev, goodix_keycode[i], 1); } if(buf[0] == 0xFF) { input_report_key(s_input_dev, goodix_keycode[i], 0); } }}#endifstatic int goodix_key_input_init(struct goodix_ts_data *ts){ int i; s_input_dev = ts->input_dev; set_bit(EV_KEY, ts->input_dev->evbit); for(i = 0; i < MAX_BUTTON_CNT; i++) set_bit(goodix_keycode[i], ts->input_dev->keybit); /******wangyulu********添加time*****/#ifdef TIMER init_timer(&key_timer); key_timer.function = goodix_key_timer_handler; key_timer.expires = jiffies + KEY_DETECT_INTERVAL; add_timer(&key_timer);#endif}static int goodix_init_key(struct goodix_ts_data *ts){ int ret=-1;#ifdef EINT29 //KEY_EINT_NUM INT11 wangyulu gpio_request(S5PV210_GPH3(5), "goodix_key_int"); s3c_gpio_cfgpin(S5PV210_GPH3(5), 0xf<<20); s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN); set_irq_type(EINT_KEY, IRQ_TYPE_EDGE_RISING); gpio_free(S5PV210_GPH3(5)); KEY_EINT_EN;#else if(ts->use_irq) enable_irq(ts->client->irq);#endif uint8_t config_info[]={ 0x88,0x08,0x90,0x90,0x90,0x90,0x50,0x58,0x55,0x56, 0x0e,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00, 0x00,0x05,0x06,0x07,0x00,0xc8};#endif ret=i2c_write_key(ts->client,config_info,sizeof(config_info)); if(ret > 0) ret = 0; goodix_key_input_init(ts); //urbetter+ boy return ret;}#ifdef EINT29///add wangyulu 按键中断处理函数static irqreturn_t goodix_key_irq_handler(int irq, void *dev_id){ struct goodix_ts_data *ts = dev_id; printk("goodix_key_irq_handler\n"); //没有按下是0xff boy KEY_EINT_DIS; schedule_work(&key_work); return IRQ_HANDLED;}static void goodix_key_callback(struct work_struct *work)/////adb wangyulu interrupter{ int i; int boy_flag = 0; unsigned char buf[2]; buf[0] = 0xc5; goodix_i2c_rxdata(buf, 1); printk("key_EINT29=0x%02X\n", buf[0]); //没有按下是0xff boy for(i = 0; i < MAX_BUTTON_CNT; i++) { if((buf[0] == goodix_scancode_history[i]) || (buf[0] == goodix_scancode[i])) { goodix_scancode_history[i]= buf[0]; input_report_key(s_input_dev, goodix_keycode[i], 1); } if(buf[0] == 0xFF) { input_report_key(s_input_dev, goodix_keycode[i], 0); } } KEY_EINT_EN;}#endifstatic void utv210_gpio_init(void){ int ret = 0; VICREG = ioremap(0xf2000000, sizeof(VIC_REG)); UT210_GPIOREG = ioremap(0xe0200000, sizeof(UT210_GPIO_REG)); //wangyulu key#ifdef EINT29 set_irq_type(EINT_KEY, IRQ_TYPE_EDGE_RISING); ret = gpio_request(S5PV210_GPH3(5), "goodix_key_int"); if (ret < 0) { gpio_free(S5PV210_GPH3(5)); // now bug; TODO } ret = gpio_request(S5PV210_GPH3(5), "goodix_key_int"); s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN); gpio_free(S5PV210_GPH3(5)); //denis_wei add 2010-12-10 for touch interrupt detect UT210_GPIOREG->GPH1.GP_CON &= ~((0xf<<20) );//gph13 as input port UT210_GPIOREG->GPH1.GP_CON |= ((0xf<<20));//gph13 interrupt port UT210_GPIOREG->GPH1.GP_DAT &= ~((0x1<<20) );//gph13. output 1 UT210_GPIOREG->GPH1.GP_PUD &= ~((0x3<<20) );//gph13 pull disable UT210_GPIOREG->GPH1.GP_PUD |= ((0x2<<20));//gph13 pull-up enable#endif#ifdef TIMER s3c_gpio_cfgpin(S5PV210_GPH3(5), 0x0<<20); gpio_direction_output(S5PV210_GPH3(5), 1); s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN);#endif }/******************************************************* 功能: 触摸屏探测函数 在注册驱动时调用(要求存在对应的client); 用于IO,中断等资源申请;设备注册;触摸屏初始化等工作参数: client:待驱动的设备结构体 id:设备IDreturn: 执行结果码,0表示正常执行********************************************************/static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){ struct goodix_ts_data *ts; int ret = 0; int retry=0; int count=0; u8 testbuf[6] = {0, 0, 0, 0, 0}; struct goodix_i2c_rmi_platform_data *pdata; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "System need I2C function.\n"); ret = -ENODEV; goto err_check_functionality_failed; } ts = kzalloc(sizeof(*ts), GFP_KERNEL); if (ts == NULL) { ret = -ENOMEM; goto err_alloc_data_failed; } //utv210_gpio_init(); /***wangyulu****/ ts->client = client; i2c_set_clientdata(client, ts); pdata = client->dev.platform_data; 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_failed; } ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ret = input_register_device(ts->input_dev); if (ret) { dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name); goto err_input_register_device_failed; } utv210_gpio_init(); goodix_init_key(ts);#ifdef EINT29///wangyulu 按键中断申请 ret = request_irq(EINT_KEY, goodix_key_irq_handler, IRQ_TYPE_EDGE_RISING, client->name, ts); if( ret ) { printk("Can't allocate touchscreen's interrupt\n"); dev_err(&client->dev,"Can't allocate touchscreen's interrupt!ERRNO:%d\n", ret); goto Fail_utv210_int; } ts->use_irq = 1; KEY_EINT_DIS;#endif printk("#############line =%d\n", __LINE__);err_input_register_device_failed: input_free_device(ts->input_dev);err_input_dev_alloc_failed: i2c_set_clientdata(client, NULL);Fail_utv210_int:err_alloc_data_failed:err_check_functionality_failed: return ret;}/******************************************************* 功能: 驱动资源释放参数: client:设备结构体return: 执行结果码,0表示正常执行********************************************************/static int goodix_ts_remove(struct i2c_client *client){ struct goodix_ts_data *ts = i2c_get_clientdata(client); unregister_early_suspend(&ts->early_suspend); dev_notice(&client->dev,"The driver is removing...\n"); i2c_set_clientdata(client, NULL); input_unregister_device(ts->input_dev);#ifdef EINT29 free_irq(EINT_KEY, ts);#endif if(ts->input_dev) kfree(ts->input_dev); kfree(ts); return 0;}//停用设备static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg){ int ret; struct goodix_ts_data *ts = i2c_get_clientdata(client); if(ts->bad_data) return 0; }static int goodix_ts_resume(struct i2c_client *client){ int ret; struct goodix_ts_data *ts = i2c_get_clientdata(client); if(ts->bad_data) return 0;#ifdef EINT29 KEY_EINT_EN;#else if (ts->use_irq) { enable_irq(client->irq); }#endif return 0;}#ifdef CONFIG_HAS_EARLYSUSPENDstatic void goodix_ts_early_suspend(struct early_suspend *h){ struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_suspend(ts->client, PMSG_SUSPEND);}static void goodix_ts_late_resume(struct early_suspend *h){ struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_resume(ts->client); }#endif#undef GOODIX_I2C_NAME#define GOODIX_I2C_NAME "Goodix-key-703" //boy static const struct i2c_device_id goodix_ts_id[] = { { GOODIX_I2C_NAME, 0 }, { }};//设备驱动结构体struct i2c_driver goodix_ts_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove,#ifndef CONFIG_HAS_EARLYSUSPEND .suspend = goodix_ts_suspend, .resume = goodix_ts_resume,#endif .id_table = goodix_ts_id, .driver = { .name = GOODIX_I2C_NAME, .owner = THIS_MODULE, },};/******************************************************* 功能: 驱动加载函数return: 执行结果码,0表示正常执行********************************************************/ static int __devinit goodix_ts_init(void) { int ret; ret=i2c_add_driver(&goodix_ts_driver); return ret; }/******************************************************* 功能: 驱动卸载函数参数: client:设备结构体********************************************************/ static void __exit goodix_ts_exit(void) { i2c_del_driver(&goodix_ts_driver); }late_initcall(goodix_ts_init);module_exit(goodix_ts_exit);MODULE_DESCRIPTION("Goodix Touchscreen Driver");MODULE_LICENSE("GPL");
转载自:http://blog.csdn.net/Baiduluckyboy/article/details/6616533
更多相关文章
- android获取设备唯一标识device_token
- Android 加载图片文件 函数
- Android 获取设备宽高分辨率
- 如何获取Android设备名称(常用ADB命令介绍)
- android保持在休眠时,后台程序继续运行(让程序获取设备电源锁)
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听
- js判断当前设备是 Android 还是 iOS
- android 长按键菜单