#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/workqueue.h>
#define CMD_BUFFER 0x20
#define CMD_RESPONSE 0xa0
#define QUERY_BUFFER 0x80
#define POINT_BUFFER 0xe0
void point_buffer_read(char *buf); //¶ÁÈ¡´¥ÃþÊý¾Ý
char query_buffer_read(void); //¶ÁÈ¡query buffer
void set_interrupt_mode(void);
short command_response_read(void); //¶ÁÈ¡ÃüÁîÖ´Ðнá¹û
irqreturn_t TOUCHIRQ_Handler(int arg, void *devID);
void TSWORK_Function(struct work_struct *work);
struct i2c_client *client = NULL;
struct work_struct tswork;
int it7260_probe(struct i2c_client *clt, const struct i2c_device_id *id)
{
int ret, flags;
short cmdrlt; //±£´æÃüÁîÖ´Ðнá¹û
client = clt; //±£´æcltΪȫ¾Ö±äÁ¿
set_interrupt_mode();
cmdrlt = command_response_read();
INIT_WORK(&tswork, TSWORK_Function);
flags = IRQF_TRIGGER_LOW;
ret = request_irq(clt->irq, TOUCHIRQ_Handler, flags, clt->name, NULL);
if(ret < 0)
{
printk("irq request error\r\n");
return -EFAULT;
}
printk("irq request success\r\n");
return 0;
}
int it7260_remove(struct i2c_client *clt)
{
free_irq(clt->irq, NULL);
return 0;
}
const struct i2c_device_id table_id = {
.name = "it7260_ts",
};
struct i2c_driver it7260_driver = {
.probe = it7260_probe,
.remove = it7260_remove,
.id_table = &table_id,
.driver = {
.owner = THIS_MODULE,
.name = "it7260_ts",
}
};
module_driver(it7260_driver, i2c_add_driver, i2c_del_driver);
MODULE_LICENSE("GPL");
/*disable_irq_nosync(unsigned int irq)ºÍdisable_irq(unsigned int irq)¹¦ÄÜÏàͬ
Çø±ðÔÚÓÚnosync¿ÉÒÔÔÚÖжÏÖÐʹÓã¬disable_irqÔÚÖжÏÖÐʹÓûᵼÖÂϵͳ±ÀÀ£*/
irqreturn_t TOUCHIRQ_Handler(int arg, void *devID)
{
disable_irq_nosync(client->irq); //½øÁËÖжÏÖ®ºó¾Í¹Ø±ÕÖжÏÔٴδ¥·¢¹¦ÄÜ
schedule_work(&tswork);
return IRQ_HANDLED;
}
void TSWORK_Function(struct work_struct *work)
{
char data[14] = {0};
char query_val;
do{
query_val = query_buffer_read();
}while((query_val & 0x80) != 0x80); //¶ÁÈ¡querybufferÖªµÀÊý¾Ý¿É¶Á
point_buffer_read(data);
printk("point = 0x%x\r\n", data[0] & 0x7);
enable_irq(client->irq); //¿ªÆôÖжϴ¥·¢¹¦ÄÜ
}
void set_interrupt_mode(void)
{
char cmdaddr = CMD_BUFFER; //ÃüÁî¼Ä´æÆ÷µØÖ·
char config[4] = {0x02, 0x04, 0x01, 0x00}; //Ö÷ÃüÁî ×ÓÃüÁî ÖжÏʹÄÜ µÍµçƽ´¥·¢
struct i2c_msg msgbuf[] = {
[0] = {
.flags = 0,
.addr = client->addr,
.buf = &cmdaddr, //·¢ËÍÃüÁî¼Ä´æÆ÷µØÖ·
.len = 1,
},
[1] = {
.flags = I2C_M_NOSTART,
.addr = client->addr,
.buf = config,
.len = 4,
}
};
i2c_transfer(client->adapter, msgbuf, ARRAY_SIZE(msgbuf));
}
short command_response_read(void)
{
char cmdaddr = CMD_RESPONSE; //ÃüÁîÖ´ÐÐ״̬¼Ä´æÆ÷
char cmdrps[2] = {0}; //ÓÃÀ´½ÓÊÕÃüÁî״̬
struct i2c_msg msgbuf[] = {
[0] = {
.flags = 0,
.addr = client->addr,
.buf = &cmdaddr, //·¢ËÍÃüÁî¼Ä´æÆ÷µØÖ·
.len = 1,
},
[1] = {
.flags = I2C_M_RD,
.addr = client->addr,
.buf = cmdrps,
.len = 2,
}
};
i2c_transfer(client->adapter, msgbuf, ARRAY_SIZE(msgbuf));
return cmdrps[1] << 8 | cmdrps[0];
}
char query_buffer_read(void) //¶ÁÈ¡query buffer
{
char queryaddr = QUERY_BUFFER;
char rdata[1] = {0};
struct i2c_msg msgbuf[] = {
[0] = {
.flags = 0,
.addr = client->addr,
.buf = &queryaddr,
.len = 1,
},
[1] = {
.flags = I2C_M_RD,
.addr = client->addr,
.buf = rdata,
.len = 1,
}
};
i2c_transfer(client->adapter, msgbuf, ARRAY_SIZE(msgbuf));
return rdata[0];
}
void point_buffer_read(char *buf) //¶ÁÈ¡´¥ÃþÊý¾Ý
{
char pointaddr = POINT_BUFFER;
char rdata[14] = {0};
struct i2c_msg msgbuf[] = {
[0] = {
.flags = 0,
.addr = client->addr,
.buf = &pointaddr,
.len = 1,
},
[1] = {
.flags = I2C_M_RD,
.addr = client->addr,
.buf = rdata,
.len = 14,
}
};
i2c_transfer(client->adapter, msgbuf, ARRAY_SIZE(msgbuf));
strncpy(buf, rdata, 14);
}