我先分析一下公司手机的部分的按键的代码,平台是高通,android版本是4.4.4 即kk版本。
static const struct i2c_device_id sn7325_key_id[] = {
{"sn7325", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, sn7325_key_id);
#ifdef CONFIG_OF
static struct of_device_id sn7325_match_table[] = {
{ .compatible = "sientech,7325",},
{ },
};
#else
#define sn7325_match_table NULL
#endif
static struct i2c_driver sn7325_key_driver = { //使用的总线是I2C
.probe = sn7325_key_probe, //正确添加之后会调用probe的函数
.remove = __devexit_p(sn7325_key_remove), //一般是初始化时失败或者是probe函数中失败时移除
.driver = {
.name = "sn7325",
.owner = THIS_MODULE,
.of_match_table = sn7325_match_table, //用来匹配driver以及device的,要不然通过name,要不然就是通过sn7325_match_table
#ifdef CONFIG_PM //不过高通走的是match_table的方式
.pm = &sn7325_key_pm_ops, //电源管理的,灭屏时会调用ops中的suspend函数,亮屏时会调用resume函数,
#endif //为了省电,将按键芯片关掉或者是置于低功耗的状态
},
.id_table = sn7325_key_id, //有的驱动可以支持多种device,这个driver只支持sn7325的名为“sientech,7325”的device
};
static int __init sn7325_key_init(void)
{
return i2c_add_driver(&sn7325_key_driver); //i2c总线上增加driver,函数会遍历整个i2c上的device,
} //看这个增加的driver和之前添加到i2c
//bus上的device中的名字或者是定义的id是否相同,相同则绑定,同时调用driver的probe函数
module_init(sn7325_key_init);
static void __exit sn7325_key_exit(void)
{
i2c_del_driver(&sn7325_key_driver);
}
module_exit(sn7325_key_exit);
MODULE_DESCRIPTION("sientech sn7325 TouchScreen driver");
MODULE_LICENSE("GPL v2");
注意,一般的时候device应该是早于driver先挂载到i2c bus上的,因为在高通的devicetree中就已经早早的读取而挂载到i2c上了,所以只需要添加driver就可以了。重头戏在probe函数中。
static int sn7325_key_probe(struct i2c_client *client, //i2c的客户,i2c core管理着这些使用i2c总线的客户,提供给他们读写i2c的api
const struct i2c_device_id *id)
{
struct sn7325_key_platform_data *pdata; //一般作为driver来讲,都会有一个和driver驱动相关的结构体
struct sn7325_key_data *data; //结构体保存着该driver的状态,属性,以及函数指针,这不就是C++吗,面向对象的思想
struct input_dev *input_dev; //主人公input_dev出现了,打个!!!!!!!!!
int err;
pr_debug("gyx->sn7325 probe enter\n"); //同事的log,不过打不出来ÿ