Linux驱动之触摸屏(4)-多点触控

时间:2024-03-17 22:58:47

4.1 概述

         此驱动支持it7260触摸屏控制器,最多支持三点触摸,已在CPU: s5pc110、linux-2.6.32.9、android-2.2上测试通过。原本以为三天就能搞定,最后还是用了一个礼拜才弄完。水平有限,可能存在一些bug,请及时反馈给我(cjok.liao@gmail.com)。

         触摸屏驱动主要分为两个部分:

         I2C驱动部分:主要负责将设备挂接到I2C总线上,实现数据传输;

         输入子系统部分:负责把获取到的数据上报到用户空间。

          中断下半部采用延迟的工作队列,完成数据的解析和上报工作。

         其他都要参考控制器的数据手册来完成,比如像数据包的解析,数据传输协议(标准的I2C协议)。

 

4.2 驱动解析

 

  1. /* 
  2. * multi touch screen driver for it7260 
  3. * base on multi-touch protocol A 
  4. */  
  5. #include <linux/module.h>   
  6. #include <linux/kernel.h>   
  7. #include <linux/input.h>   
  8. #include <linux/interrupt.h>   
  9. #include <linux/pm.h>   
  10. #include <linux/slab.h>   
  11. #include <asm/io.h>   
  12. #include <linux/i2c.h>   
  13. #include <linux/timer.h>   
  14.   
  15. /* buffer address */  
  16. #define CMD_BUF     0x20    /* command buffer (write only) */   
  17. #define SYS_CMD_BUF 0x40    /* systerm command buffer (write only) */   
  18. #define QUERY_BUF   0x80    /* query buffer (read only) */   
  19. #define CMD_RSP_BUF 0xA0    /* command response buffer (read only) */   
  20. #define SYS_CMD_RSP_BUF 0xC0    /* systerm command response buffer (read only) */   
  21. #define POINT_INFO_BUF  0xE0    /* point information buffer (read only) */   
  22.   
  23. /* 构造一个触摸屏设备结构体 */  
  24. struct it7260_ts_priv {  
  25.     struct i2c_client *client; /* I2C 设备 */  
  26.     struct input_dev *input;   /* 输入设备结构体 */  
  27.     struct delayed_work work;  /* 延迟工作队列 */  
  28.     struct mutex mutex;        /* 互斥体 */  
  29.     int irq;                   /* 中断 */  
  30. };  
  31.   
  32. /** 
  33.  * 发送和接受函数,虽然内核中提供了i2c_master_recv和i2c_master_send, 
  34.  * 但是这两个函数只适合单个msg的情况 
  35. */  
  36. /** 
  37. * i2c_master_read_it7260 - issue two I2C message in master receive mode 
  38. * @client: handler to slave device 
  39. * @buf_index: buffer address 
  40. * @buf_data: where to store data read from slave 
  41. * @len_data: the bytes of buf_data to read  
  42. * 
  43. * returns negative errno, or else the number of bytes read 
  44. */  
  45. static int i2c_master_read_it7260(struct i2c_client *client,   
  46.         unsigned char buf_index, unsigned char *buf_data,   
  47.         unsigned short len_data)  
  48. {  
  49.     int ret;  
  50.     struct i2c_msg msgs[2] = {  
  51.         {  
  52.             .addr = client->addr,  
  53.             .flags = I2C_M_NOSTART,  
  54.             .len = 1,  
  55.             .buf = &buf_index,  
  56.         },  
  57.         {  
  58.             .addr = client->addr,  
  59.             .flags = I2C_M_RD,  
  60.             .len = len_data,  
  61.             .buf = buf_data,  
  62.         }  
  63.     };  
  64.   
  65.     ret = i2c_transfer(client->adapter, msgs, 2);  
  66.   
  67.     return (ret == 2) ? len_data : ret;  
  68. }  
  69.   
  70. /** 
  71. * i2c_master_write_it7260 - issue a single I2C message in master transmit mode 
  72. * @client: handler to slave device 
  73. * @buf_index: buffer address 
  74. * @buf_data: data that wile be write to the slave 
  75. * @len_data: the bytes of buf_data to write 
  76. * 
  77. * returns negative errno, or else the number of bytes written 
  78. */  
  79. static int i2c_master_write_it7260(struct i2c_client *client,   
  80.         unsigned char buf_index, unsigned char const *buf_data,  
  81.         unsigned short len_data)  
  82. {  
  83.     unsigned char buf[2];  
  84.     int ret;  
  85.   
  86.     struct i2c_msg msgs[1] = {  
  87.         {  
  88.             .addr = client->addr,  
  89.             .flags = 0, /* default write flag */  
  90.             .len = len_data + 1,   
  91.             .buf = buf,  
  92.         }  
  93.     };  
  94.   
  95.     buf[0] = buf_index;  
  96.     memcpy(&buf[1], buf_data, len_data);  
  97.   
  98.     ret = i2c_transfer(client->adapter, msgs, 1);  
  99.       
  100.     return (ret == 1) ? sizeof(buf) : ret;  
  101. }  
  102.   
  103. /** 
  104. * 延迟工作,当产生中断时调用,负责从I2C总线上读取数据,然后按照数 
  105. * 据手册上的进行解析,然后进行上报。 
  106. */  
  107. static void it7260_ts_poscheck(struct work_struct *work)  
  108. {  
  109.     struct it7260_ts_priv *priv = container_of(work,   
  110.                 struct it7260_ts_priv, work.work);  
  111.     unsigned char buf[14];  
  112.     unsigned short xpos[3] = {0}, ypos[3] = {0};  
  113.     unsigned char event[3] = {0};  
  114.     unsigned char query = 0;  
  115.     int ret, i;  
  116.   
  117.     mutex_lock(&priv->mutex);  
  118.   
  119.     i2c_master_read_it7260(priv->client, QUERY_BUF, &query, 1);  
  120.     if (!(query & 0x80)) {  
  121.         dev_err(&priv->client->dev, "no finger touch\n");  
  122.         goto out;  
  123.     }  
  124.   
  125.     memset(&buf, 0, sizeof(buf));  
  126.   
  127.     ret = i2c_master_read_it7260(priv->client, POINT_INFO_BUF, buf, 14);  
  128.     if (ret != 14) {  
  129.         dev_err(&priv->client->dev, "failed to read point info buffer\n");  
  130.         goto out;  
  131.     }  
  132.   
  133.     /* touch key */  
  134.     if (buf[0] == 0x41) {  
  135.         dev_info(&priv->client->dev, "the key number %d\n", buf[1]);  
  136.         if (buf[1] == 0x04)  
  137.             input_report_key(priv->input, KEY_HOME, !!buf[2]);  
  138.         else if (buf[1] == 0x03)  
  139.             input_report_key(priv->input, KEY_MENU, !!buf[2]);  
  140.         else if (buf[1] == 0x02)  
  141.             input_report_key(priv->input, KEY_BACK, !!buf[2]);  
  142.         else if (buf[1] == 0x01)  
  143.             input_report_key(priv->input, KEY_POWER, !!buf[2]);  
  144.         else  
  145.             goto out;  
  146.   
  147.         input_sync(priv->input);  
  148.         goto out;  
  149.     }  
  150.   
  151.     /* finger 0 */  
  152.     if (buf[0] & 0x01) {  
  153.         xpos[0] = ((buf[3] & 0x0F) << 8) | buf[2];  
  154.         ypos[0] = ((buf[3] & 0xF0) << 4) | buf[4];  
  155.         event[0] = buf[5] & 0x0F;  
  156.     }  
  157.   
  158.     /* finger 1 */  
  159.     if (buf[0] & 0x02) {  
  160.         xpos[1] = ((buf[7] & 0x0F) << 8) | buf[6];  
  161.         ypos[1] = ((buf[7] & 0xF0) << 4) | buf[8];  
  162.         event[1] = buf[9] & 0x0F;  
  163.     }  
  164.   
  165.     /* finger 2 */  
  166.     if (buf[0] & 0x04) {  
  167.         xpos[2] = ((buf[11] & 0x0F) << 8) | buf[10];  
  168.         ypos[2] = ((buf[11] & 0xF0) << 4) | buf[12];  
  169.         event[2] = buf[13] & 0x0F;  
  170.     }  
  171.   
  172.     for (i = 0; i < 3; i++) {  
  173.         input_report_abs(priv->input, ABS_MT_POSITION_X, ypos[i]);  
  174.         input_report_abs(priv->input, ABS_MT_POSITION_Y, xpos[i]);  
  175.         input_report_abs(priv->input, ABS_MT_TOUCH_MAJOR, !!event[i]);  
  176.         input_report_abs(priv->input, ABS_MT_WIDTH_MAJOR, 0);  
  177.         input_mt_sync(priv->input);  
  178.         dev_info(&priv->client->dev, "finger %d > xpos = %d, \  
  179.         ypos = %d, event = %d\n", i, ypos[i], xpos[i], event[i]);  
  180.     }  
  181.     input_sync(priv->input);  
  182.   
  183. out:  
  184.     mutex_unlock(&priv->mutex);  
  185.     enable_irq(priv->irq);  
  186. }  
  187.   
  188. /* 中断服务子程序,产生中断后,延迟(HZ/20)个tick后调度工作 */  
  189. static irqreturn_t it7260_ts_isr(int irq, void *dev_id)  
  190. {  
  191.     struct it7260_ts_priv *priv = dev_id;  
  192.   
  193.     disable_irq_nosync(irq);  
  194.     schedule_delayed_work(&priv->work, HZ / 20);  
  195.   
  196.     return IRQ_HANDLED;  
  197. }  
  198.   
  199. /** 
  200. * it7260_identify_capsensor - identify capacitance sensor model 
  201. * 
  202. * returns error -1, or else suc 0 
  203. */  
  204. static int it7260_identify_capsensor(struct i2c_client *client)  
  205. {  
  206.     unsigned char buf[10];  
  207.     unsigned char query = 0;  
  208.   
  209.     do {  
  210.         i2c_master_read_it7260(client, QUERY_BUF, &query, 1);  
  211.     } while (query & 0x01);  
  212.   
  213.     /* 0x00: the command of identify cap sensor */  
  214.     buf[0] = 0x00;    
  215.     i2c_master_write_it7260(client, CMD_BUF, buf, 1);  
  216.   
  217.     do {  
  218.         i2c_master_read_it7260(client, QUERY_BUF, &query, 1);  
  219.     } while (query & 0x01);  
  220.   
  221.     memset(&buf, 0, sizeof(buf));  
  222.     i2c_master_read_it7260(client, CMD_RSP_BUF, buf, 10);  
  223.     dev_err(&client->dev, "len = %d, %c%c%c\n", buf[0], buf[1], buf[2], buf[3]);  
  224.     if (buf[1] != \'I\' || buf[2] != \'T\' || buf[3] != \'E\')   
  225.         return -1;  
  226.   
  227.     return 0;  
  228. }  
  229.   
  230. /* probe函数,在i2c设备和i2c驱动匹配时会调用此函数来完成相应的工作 */  
  231. static int it7260_ts_probe(struct i2c_client *client,   
  232.             const struct i2c_device_id *idp)  
  233. {  
  234.     struct it7260_ts_priv *priv;  
  235.     struct input_dev *input;  
  236.     int error;  
  237.   
  238.     /* 识别此设备型号是否为it7260 */  
  239.     error = it7260_identify_capsensor(client);  
  240.     if (error) {  
  241.         dev_err(&client->dev, "cannot identify the touch screen\n");  
  242.         goto err0;  
  243.     }  
  244.   
  245.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  246.     if (!priv) {  
  247.         dev_err(&client->dev, "failed to allocate driver data\n");  
  248.         error = -ENOMEM;  
  249.         goto err0;  
  250.     }  
  251.       
  252.     /* 初始化mutex */  
  253.     mutex_init(&priv->mutex);  
  254.   
  255.     dev_set_drvdata(&client->dev, priv);  
  256.   
  257.     /* 分配一个input设备 */  
  258.     input = input_allocate_device();  
  259.     if (!input) {  
  260.         dev_err(&client->dev, "failed to allocate input device\n");  
  261.         error = -ENOMEM;  
  262.         goto err1;  
  263.     }  
  264.   
  265.     /* 设置input设备所支持的事件类型 */  
  266.     input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);  
  267.   
  268.     input_set_capability(input, EV_KEY, KEY_MENU);  
  269.     input_set_capability(input, EV_KEY, KEY_BACK);  
  270.     input_set_capability(input, EV_KEY, KEY_HOME);  
  271.     input_set_capability(input, EV_KEY, KEY_POWER);  
  272.   
  273.     input_set_abs_params(input, ABS_MT_POSITION_X, 0, 600, 0, 0);  
  274.     input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 1024, 0, 0);  
  275.     input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);  
  276.     input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 2, 0, 0);  
  277.   
  278.     input->name = "it7260 touch screen";  
  279.     input->phys = "I2C";  
  280.     input->id.bustype = BUS_I2C;  
  281.   
  282.     input_set_drvdata(input, priv);  
  283.   
  284.     priv->client = client;  
  285.     priv->input = input;  
  286.     /* 初始化延迟工作队列 */  
  287.     INIT_DELAYED_WORK(&priv->work, it7260_ts_poscheck);  
  288.     priv->irq = client->irq;  
  289.   
  290.     /* 向输入子系统注册此input设备 */  
  291.     error = input_register_device(input);  
  292.     if (error) {  
  293.         dev_err(&client->dev, "failed to register input device\n");  
  294.         goto err1;  
  295.     }  
  296.   
  297.     /* 注册中断,低电平触发 */  
  298.     error = request_irq(priv->irq, it7260_ts_isr, IRQF_TRIGGER_LOW,  
  299.                         client->name, priv);  
  300.     if (error) {  
  301.         dev_err(&client->dev, "unable to request touchscreen IRQ\n");  
  302.         goto err2;  
  303.     }  
  304.   
  305.     device_init_wakeup(&client->dev, 1);  
  306.     return 0;  
  307.       
  308. err2:  
  309.     input_unregister_device(input);  
  310.     input = NULL;  
  311. err1:  
  312.     input_free_device(input);  
  313.     kfree(priv);  
  314. err0:  
  315.     dev_set_drvdata(&client->dev, NULL);  
  316.     return error;  
  317. }  
  318.   
  319. /* 当没有使用此设备时调用移除函数进行注销 */  
  320. static int __devexit it7260_ts_remove(struct i2c_client *client)  
  321. {  
  322.     struct it7260_ts_priv *priv = dev_get_drvdata(&client->dev);  
  323.   
  324.     free_irq(priv->irq, priv);  
  325.     input_unregister_device(priv->input);  
  326.     kfree(priv);  
  327.   
  328.     dev_set_drvdata(&client->dev, NULL);  
  329.   
  330.     return 0;  
  331. }  
  332.   
  333. /* 电源管理函数 */  
  334. static int it7260_ts_suspend(struct i2c_client *client, pm_message_t mesg)  
  335. {  
  336.     int ret = -1;  
  337.     u8 suspend_cmd[] = {0x04, 0x00, 0x02};  
  338.     struct it7260_ts_priv *priv = i2c_get_clientdata(client);  
  339.   
  340.     if (device_may_wakeup(&client->dev)) {  
  341.         enable_irq_wake(priv->irq);  
  342.         if (sizeof(suspend_cmd) == i2c_master_write_it7260(client,   
  343.                     CMD_BUF, suspend_cmd, 3))   
  344.             ret = 0;  
  345.     }   
  346.   
  347.     return ret;  
  348. }  
  349.   
  350. static int it7260_ts_resume(struct i2c_client *client)  
  351. {  
  352.     int ret = -1;  
  353.     unsigned char query;  
  354.     struct it7260_ts_priv *priv = i2c_get_clientdata(client);  
  355.   
  356.     if (device_may_wakeup(&client->dev)) {  
  357.         i2c_master_read_it7260(client, QUERY_BUF, &query, 1);  
  358.         disable_irq_wake(priv->irq);  
  359.         ret = 0;  
  360.     }  
  361.   
  362.     return ret;  
  363. }  
  364.   
  365. /* 驱动支持的设备列表,用来匹配 */  
  366. static const struct i2c_device_id it7260_ts_id[] = {  
  367.     {"IT7260", 0},  
  368.     {}          /* should not omitted */  
  369. };  
  370. MODULE_DEVICE_TABLE(i2c, it7260_ts_id);  
  371.   
  372. static struct i2c_driver it7260_ts_driver = {  
  373.     .driver = {  
  374.         .name = "IT7260-ts",  
  375.     },  
  376.     .probe = it7260_ts_probe,  
  377.     .remove = __devexit_p(it7260_ts_remove),  
  378.     .suspend = it7260_ts_suspend,  
  379.     .resume = it7260_ts_resume,  
  380.     .id_table = it7260_ts_id,  
  381. };  
  382.   
  383. /* 模块加载函数 */  
  384. static int __init it7260_ts_init(void)  
  385. {  
  386.     return i2c_add_driver(&it7260_ts_driver);     
  387. }  
  388.   
  389. /* 模块卸载函数 */  
  390. static void __exit it7260_ts_exit(void)  
  391. {  
  392.     i2c_del_driver(&it7260_ts_driver);  
  393. }  
  394.   
  395. module_init(it7260_ts_init);  
  396. module_exit(it7260_ts_exit);  
  397.   
  398. MODULE_LICENSE("GPL");  
  399. MODULE_AUTHOR("CJOK <cjok.liao@gmail.com>");  
  400. MODULE_DESCRIPTION("it7260 touchscreen driver");  
/*
* multi touch screen driver for it7260
* base on multi-touch protocol A
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/timer.h>

/* buffer address */
#define CMD_BUF		0x20	/* command buffer (write only) */
#define SYS_CMD_BUF	0x40	/* systerm command buffer (write only) */
#define QUERY_BUF	0x80	/* query buffer (read only) */
#define CMD_RSP_BUF	0xA0	/* command response buffer (read only) */
#define SYS_CMD_RSP_BUF	0xC0	/* systerm command response buffer (read only) */
#define POINT_INFO_BUF	0xE0	/* point information buffer (read only) */

/* 构造一个触摸屏设备结构体 */
struct it7260_ts_priv {
	struct i2c_client *client; /* I2C 设备 */
	struct input_dev *input;   /* 输入设备结构体 */
	struct delayed_work work;  /* 延迟工作队列 */
	struct mutex mutex;        /* 互斥体 */
	int irq;                   /* 中断 */
};

/**
 * 发送和接受函数,虽然内核中提供了i2c_master_recv和i2c_master_send,
 * 但是这两个函数只适合单个msg的情况
*/
/**
* i2c_master_read_it7260 - issue two I2C message in master receive mode
* @client: handler to slave device
* @buf_index: buffer address
* @buf_data: where to store data read from slave
* @len_data: the bytes of buf_data to read 
*
* returns negative errno, or else the number of bytes read
*/
static int i2c_master_read_it7260(struct i2c_client *client, 
		unsigned char buf_index, unsigned char *buf_data, 
		unsigned short len_data)
{
	int ret;
	struct i2c_msg msgs[2] = {
		{
			.addr = client->addr,
			.flags = I2C_M_NOSTART,
			.len = 1,
			.buf = &buf_index,
		},
		{
			.addr = client->addr,
			.flags = I2C_M_RD,
			.len = len_data,
			.buf = buf_data,
		}
	};

	ret = i2c_transfer(client->adapter, msgs, 2);

	return (ret == 2) ? len_data : ret;
}

/**
* i2c_master_write_it7260 - issue a single I2C message in master transmit mode
* @client: handler to slave device
* @buf_index: buffer address
* @buf_data: data that wile be write to the slave
* @len_data: the bytes of buf_data to write
*
* returns negative errno, or else the number of bytes written
*/
static int i2c_master_write_it7260(struct i2c_client *client, 
		unsigned char buf_index, unsigned char const *buf_data,
		unsigned short len_data)
{
	unsigned char buf[2];
	int ret;

	struct i2c_msg msgs[1] = {
		{
			.addr = client->addr,
			.flags = 0, /* default write flag */
			.len = len_data + 1, 
			.buf = buf,
		}
	};

	buf[0] = buf_index;
	memcpy(&buf[1], buf_data, len_data);

	ret = i2c_transfer(client->adapter, msgs, 1);
	
	return (ret == 1) ? sizeof(buf) : ret;
}

/**
* 延迟工作,当产生中断时调用,负责从I2C总线上读取数据,然后按照数
* 据手册上的进行解析,然后进行上报。
*/
static void it7260_ts_poscheck(struct work_struct *work)
{
	struct it7260_ts_priv *priv = container_of(work, 
	 			struct it7260_ts_priv, work.work);
	unsigned char buf[14];
	unsigned short xpos[3] = {0}, ypos[3] = {0};
	unsigned char event[3] = {0};
	unsigned char query = 0;
	int ret, i;

	mutex_lock(&priv->mutex);

	i2c_master_read_it7260(priv->client, QUERY_BUF, &query, 1);
	if (!(query & 0x80)) {
		dev_err(&priv->client->dev, "no finger touch\n");
		goto out;
	}

	memset(&buf, 0, sizeof(buf));

	ret = i2c_master_read_it7260(priv->client, POINT_INFO_BUF, buf, 14);
	if (ret != 14) {
		dev_err(&priv->client->dev, "failed to read point info buffer\n");
		goto out;
	}

	/* touch key */
	if (buf[0] == 0x41) {
		dev_info(&priv->client->dev, "the key number %d\n", buf[1]);
		if (buf[1] == 0x04)
			input_report_key(priv->input, KEY_HOME, !!buf[2]);
		else if (buf[1] == 0x03)
			input_report_key(priv->input, KEY_MENU, !!buf[2]);
		else if (buf[1] == 0x02)
			input_report_key(priv->input, KEY_BACK, !!buf[2]);
		else if (buf[1] == 0x01)
			input_report_key(priv->input, KEY_POWER, !!buf[2]);
		else
			goto out;

		input_sync(priv->input);
		goto out;
	}

	/* finger 0 */
	if (buf[0] & 0x01) {
		xpos[0] = ((buf[3] & 0x0F) << 8) | buf[2];
		ypos[0] = ((buf[3] & 0xF0) << 4) | buf[4];
		event[0] = buf[5] & 0x0F;
	}

	/* finger 1 */
	if (buf[0] & 0x02) {
		xpos[1] = ((buf[7] & 0x0F) << 8) | buf[6];
		ypos[1] = ((buf[7] & 0xF0) << 4) | buf[8];
		event[1] = buf[9] & 0x0F;
	}

	/* finger 2 */
	if (buf[0] & 0x04) {
		xpos[2] = ((buf[11] & 0x0F) << 8) | buf[10];
		ypos[2] = ((buf[11] & 0xF0) << 4) | buf[12];
		event[2] = buf[13] & 0x0F;
	}

	for (i = 0; i < 3; i++) {
		input_report_abs(priv->input, ABS_MT_POSITION_X, ypos[i]);
		input_report_abs(priv->input, ABS_MT_POSITION_Y, xpos[i]);
		input_report_abs(priv->input, ABS_MT_TOUCH_MAJOR, !!event[i]);
		input_report_abs(priv->input, ABS_MT_WIDTH_MAJOR, 0);
		input_mt_sync(priv->input);
		dev_info(&priv->client->dev, "finger %d > xpos = %d, \
		ypos = %d, event = %d\n", i, ypos[i], xpos[i], event[i]);
	}
	input_sync(priv->input);

out:
	mutex_unlock(&priv->mutex);
	enable_irq(priv->irq);
}

/* 中断服务子程序,产生中断后,延迟(HZ/20)个tick后调度工作 */
static irqreturn_t it7260_ts_isr(int irq, void *dev_id)
{
	struct it7260_ts_priv *priv = dev_id;

	disable_irq_nosync(irq);
	schedule_delayed_work(&priv->work, HZ / 20);

	return IRQ_HANDLED;
}

/**
* it7260_identify_capsensor - identify capacitance sensor model
*
* returns error -1, or else suc 0
*/
static int it7260_identify_capsensor(struct i2c_client *client)
{
	unsigned char buf[10];
	unsigned char query = 0;

	do {
		i2c_master_read_it7260(client, QUERY_BUF, &query, 1);
	} while (query & 0x01);

	/* 0x00: the command of identify cap sensor */
	buf[0] = 0x00;	
	i2c_master_write_it7260(client, CMD_BUF, buf, 1);

	do {
		i2c_master_read_it7260(client, QUERY_BUF, &query, 1);
	} while (query & 0x01);

	memset(&buf, 0, sizeof(buf));
	i2c_master_read_it7260(client, CMD_RSP_BUF, buf, 10);
	dev_err(&client->dev, "len = %d, %c%c%c\n", buf[0], buf[1], buf[2], buf[3]);
	if (buf[1] != \'I\' || buf[2] != \'T\' || buf[3] != \'E\') 
		return -1;

	return 0;
}

/* probe函数,在i2c设备和i2c驱动匹配时会调用此函数来完成相应的工作 */
static int it7260_ts_probe(struct i2c_client *client, 
			const struct i2c_device_id *idp)
{
	struct it7260_ts_priv *priv;
	struct input_dev *input;
	int error;

	/* 识别此设备型号是否为it7260 */
	error = it7260_identify_capsensor(client);
	if (error) {
		dev_err(&client->dev, "cannot identify the touch screen\n");
		goto err0;
	}

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		dev_err(&client->dev, "failed to allocate driver data\n");
		error = -ENOMEM;
		goto err0;
	}
	
	/* 初始化mutex */
	mutex_init(&priv->mutex);

	dev_set_drvdata(&client->dev, priv);

	/* 分配一个input设备 */
	input = input_allocate_device();
	if (!input) {
		dev_err(&client->dev, "failed to allocate input device\n");
		error = -ENOMEM;
		goto err1;
	}

	/* 设置input设备所支持的事件类型 */
	input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);

	input_set_capability(input, EV_KEY, KEY_MENU);
	input_set_capability(input, EV_KEY, KEY_BACK);
	input_set_capability(input, EV_KEY, KEY_HOME);
	input_set_capability(input, EV_KEY, KEY_POWER);

	input_set_abs_params(input, ABS_MT_POSITION_X, 0, 600, 0, 0);
	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 1024, 0, 0);
	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);
	input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 2, 0, 0);

	input->name = "it7260 touch screen";
	input->phys = "I2C";
	input->id.bustype = BUS_I2C;

	input_set_drvdata(input, priv);

	priv->client = client;
	priv->input = input;
	/* 初始化延迟工作队列 */
	INIT_DELAYED_WORK(&priv->work, it7260_ts_poscheck);
	priv->irq = client->irq;

	/* 向输入子系统注册此input设备 */
	error = input_register_device(input);
	if (error) {
		dev_err(&client->dev, "failed to register input device\n");
		goto err1;
	}

	/* 注册中断,低电平触发 */
	error = request_irq(priv->irq, it7260_ts_isr, IRQF_TRIGGER_LOW,
						client->name, priv);
	if (error) {
		dev_err(&client->dev, "unable to request touchscreen IRQ\n");
		goto err2;
	}

	device_init_wakeup(&client->dev, 1);
	return 0;
	
err2:
	input_unregister_device(input);
	input = NULL;
err1:
	input_free_device(input);
	kfree(priv);
err0:
	dev_set_drvdata(&client->dev, NULL);
	return error;
}

/* 当没有使用此设备时调用移除函数进行注销 */
static int __devexit it7260_ts_remove(struct i2c_client *client)
{
	struct it7260_ts_priv *priv = dev_get_drvdata(&client->dev);

	free_irq(priv->irq, priv);
	input_unregister_device(priv->input);
	kfree(priv);

	dev_set_drvdata(&client->dev, NULL);

	return 0;
}

/* 电源管理函数 */
static int it7260_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
	int ret = -1;
	u8 suspend_cmd[] = {0x04, 0x00, 0x02};
	struct it7260_ts_priv *priv = i2c_get_clientdata(client);

	if (device_may_wakeup(&client->dev)) {
		enable_irq_wake(priv->irq);
		if (sizeof(suspend_cmd) == i2c_master_write_it7260(client, 
					CMD_BUF, suspend_cmd, 3)) 
			ret = 0;
	} 

	return ret;
}

static int it7260_ts_resume(struct i2c_client *client)
{
	int ret = -1;
	unsigned char query;
	struct it7260_ts_priv *priv = i2c_get_clientdata(client);

	if (device_may_wakeup(&client->dev)) {
		i2c_master_read_it7260(client, QUERY_BUF, &query, 1);
		disable_irq_wake(priv->irq);
		ret = 0;
	}

	return ret;
}

/* 驱动支持的设备列表,用来匹配 */
static const struct i2c_device_id it7260_ts_id[] = {
	{"IT7260", 0},
	{}			/* should not omitted */
};
MODULE_DEVICE_TABLE(i2c, it7260_ts_id);

static struct i2c_driver it7260_ts_driver = {
	.driver = {
		.name = "IT7260-ts",
	},
	.probe = it7260_ts_probe,
	.remove = __devexit_p(it7260_ts_remove),
	.suspend = it7260_ts_suspend,
	.resume = it7260_ts_resume,
	.id_table = it7260_ts_id,
};

/* 模块加载函数 */
static int __init it7260_ts_init(void)
{
	return i2c_add_driver(&it7260_ts_driver);	
}

/* 模块卸载函数 */
static void __exit it7260_ts_exit(void)
{
	i2c_del_driver(&it7260_ts_driver);
}

module_init(it7260_ts_init);
module_exit(it7260_ts_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CJOK <cjok.liao@gmail.com>");
MODULE_DESCRIPTION("it7260 touchscreen driver");

 

 

完整的源码可以通过git来下载:git clone git://github.com/cjok/it7260.git