Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1595014
  • 博文数量: 204
  • 博客积分: 2215
  • 博客等级: 大尉
  • 技术积分: 4427
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-06 08:03
个人简介

气质,源于心灵的自信!

文章存档

2018年(1)

2017年(1)

2016年(1)

2015年(18)

2014年(20)

2013年(30)

2012年(119)

2011年(14)

分类: LINUX

2012-07-22 11:48:20

接着上回分解:
上节向系统注册了I2C client设备,光有设备不行啊,还要有驱动才能工作,下面就看他们驱动,还以isa1200马达为例。
static const struct i2c_device_id isa1200_id[] = {
 { "isa1200_1", 0 },
 { },
};
 
/*isa1200马达的驱动结构体*/
static struct i2c_driver isa1200_driver = {
 .driver = {
  .name = "isa1200",
 },
 .probe  = isa1200_probe,
 .remove  = __devexit_p(isa1200_remove),
 .suspend = isa1200_suspend,
 .resume  = isa1200_resume,
 .id_table = isa1200_id,
};
 
/*该驱动结构的注册函数*/
static int __init isa1200_init(void)
{
 return i2c_add_driver(&isa1200_driver);
}
 
module_init(isa1200_init);
 
下面分析i2c_add_driver(&isa1200_driver)是个这么样的过程。
static inline int i2c_add_driver(struct i2c_driver *driver)
{
 return i2c_register_driver(THIS_MODULE, driver);
}
这个函数没什么看的,继续往下跟踪:
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
 /*把该驱动挂载到I2C总线上*/
 driver->driver.owner = owner;
 driver->driver.bus = &i2c_bus_type;
 
 /*向该总线注册该驱动,在注册该驱动时,由于总线有probe函数,所有先调用总线的probe函数*/
 res = driver_register(&driver->driver);
 
 /*初始化该driver所支持的client链表*/
 INIT_LIST_HEAD(&driver->clients);
 
 /*遍历该I2C总线上的adapter设备,并为每一个设备和该driver调用__process_new_driver函数*/
 bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
 return 0;
}
遍历的目的是:该驱动支持的设备有可能在不同的adapter上都有。
跟进__process_new_driver函数,看看是什么东东。
static int __process_new_driver(struct device *dev, void *data)
{
 /*设备类型必须为i2c_adapter_type*/
 if (dev->type != &i2c_adapter_type)
  return 0;

 return i2c_do_add_adapter(data, to_i2c_adapter(dev));
}
继续分解
static int i2c_do_add_adapter(struct i2c_driver *driver,
         struct i2c_adapter *adap)
{
 /*该函数马达驱动没有用到*/
 i2c_detect(adap, driver);
 
 /*如果该函数不为空,则调用该函数,其实也是空函数*/
 if (driver->attach_adapter) {
    driver->attach_adapter(adap);
 }
 return 0;
}
下面看下I2C总线的注册过程:
先看下其结构体:
struct bus_type i2c_bus_type = {
 .name  = "i2c",
 .match  = i2c_device_match,
 .probe  = i2c_device_probe,
 .remove  = i2c_device_remove,
 .shutdown = i2c_device_shutdown,
 .pm  = &i2c_device_pm_ops,
};
其中总线的probe函数会在,挂载该总线上得驱动和设备匹配的时候调用,驱动的probe函数得不到调用
static int __init i2c_init(void)
{
 retval = bus_register(&i2c_bus_type);
}
postcore_initcall(i2c_init);
 
下面看下i2c_device_probe函数是怎么探测的。
static int i2c_device_probe(struct device *dev)
{
 /*从设备找到client*/
 struct i2c_client *client = i2c_verify_client(dev);
 struct i2c_driver *driver;
 
 /*从设备driver找到该设备的i2c驱动*/
 driver = to_i2c_driver(dev->driver);
 
 /*把该I2C的驱动和client的driver绑定*/
 client->driver = driver;
 
 /*调用该driver的probe函数*/
 status = driver->probe(client, i2c_match_id(driver->id_table, client));
}
关于匹配的过程,是调用总线的match函数:
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
 struct i2c_client *client = i2c_verify_client(dev);
 struct i2c_driver *driver;
 
 driver = to_i2c_driver(drv);
 /*有client的name与i2c driver的id_table匹配比较*/
 if (driver->id_table)
  return i2c_match_id(driver->id_table, client) != NULL;
 return 0;
}
今天就写到这吧,有空了明天继续写。

阅读(4163) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~