i2c总线驱动模型大致如图

android i2c工具 i2c_new_device_链表

android i2c工具 i2c_new_device_3c_02

android i2c工具 i2c_new_device_3c_03


前者为i2c_client,后者为i2c_driver,两者通过名字“at24c08”进行匹配。

i2c实例化操作
2.1 通过总线号申请
定义一个包含名字,设备地址的i2c_board_info结构体,通过i2c_register_board_info调用list_add_tail添加至__i2c_board_list链表
使用限制:必须在 i2c_register_adapter 之前 i2c_register_board_info,所以不适合执行insmod动态加载

2.2 直接调用i2c_new_device, i2c_new_probed_device(核心 i2c_new_device )
两者不同之处在于i2c_new_probed_device 会调用probe函数根据设备地址遍历适配器判别是否挂载有该设备,有则调用i2c_new_device 创建;而i2c_new_device则直接认为该设备已经存在,直接创建。

2.3 从用户空间创建/删除设备

创建设备: echo at24c08 0x50 > /sys/devices/platform/s3c2440-i2c/i2c-0/new_device

new_device会触发i2c_sysfs_new_device进而调用i2c_new_device注册

删除设备: echo 0x50 > /sys/devices/platform/s3c2440-i2c/i2c-0/delete_device

delete_device会触发i2c_sysfs_delete_device进而调用i2c_unregister_device卸载

2.4

以上3种方法都有一个共同的不足之处,就是都要事先确定适配器(I2C总线,I2C控制器),倘若事先不知道该I2C设备在哪个适配器上,可以去该class下的所有的适配器上查找。此外上一些I2C设备的地址是一样,怎么继续辨别它是哪一款设备?可以用detect函数进行进一步判别。

android i2c工具 i2c_new_device_链表_04

去"class"下的I2C适配器,用"detect"函数来确定能否找到"address_list"里的设备,如果能找到就调用i2c_new_device来注册i2c_client, 这会和i2c_driver的id_table比较,如果匹配,调用"probe"函数。

流程大致如下

调用i2c_add_driver(i2c_register_driver)将driver添加至i2c_bus_type的i2c driver链表;并且将所有匹配的未绑定的设备调用probe函数

android i2c工具 i2c_new_device_实例化_05

调用__process_new_driver,遍历已经存在的适配器; 对于每一个适配器,调用它的函数确定address_list里的设备是否存在,如果存在,再调用detect进一步确定、设置,然后i2c_new_device创建设备。

调用关系如下

i2c_for_each_dev(driver, __process_new_driver); //遍历已经存在的适配器

__process_new_driver

i2c_do_add_adapter

i2c_detect //检测确认该设备是否在该适配器上

i2c_detect_address //调用probe,detect函数确认

i2c_new_device