如何实例化i2c_client(四法)
一、在板文件进行client的实例化
在内核的初始化中(例如在板文件中)定义设备的信息。这种操作的前提是内核编译的时候已经确定有哪些i2c设备和它们的地址,还要知道连接的总线的编号。
比如在板文件/arch/arm/mach-XXX/board_XXX.c中可以用类似下面的代码来注册i2c设备的信息。
1. static struct i2c_board_info __initdata uio_i2c_board_info[] = {
2. {
3. I2C_BOARD_INFO("dev_name0", 0x2d),
5. },
6. {
7. I2C_BOARD_INFO("dev_name1", 0x52),
9. },
10. {
11. I2C_BOARD_INFO("dev_name2", 0x57),
13. },
14. };
15.
16. static void __init uio_init(void)
17. {
18. (...)
19. i2c_register_board_info(1, uio_i2c_board_info,
20. ARRAY_SIZE(uio_i2c_board_info));
21. (...)
22. }
这样注册之后,i2c_adapter注册的时候就会扫描所有的已注册的i2c_board_info,并为连接自己的i2c设备实例化一个i2c_client。
这样一来,i2c_driver注册的时候,i2c_client就会和i2c_driver绑定了(注册的NAME必须一致),i2c_driver的probe函数被调用。
二、枚举设备
使用i2c_new_device()或者i2c_new_probed_device()在设备驱动文件进行client的实例化。
上文中提到的第一种方法有诸多限制,必须在编译内核之前就知道有哪些i2c设备和它们的地址以及说i2c的总线编号。
但有时内核开发者移植系统的时候也不知道有哪些i2c设备或者到底有多少i2c总线。在这种情况下就需要用到i2c_new_device()了。它的原型是:
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
这个函数将会使用info提供的信息建立一个i2c_client并与第一个参数指向的i2c_adapter绑定。返回的参数是一个i2c_client指针。
驱动中可以直接使用i2c_client指针和设备通信了。这个方法是一个比较简单的方法。
获取i2c_adapter指针的函数是:
struct i2c_adapter* i2c_get_adapter(int id);// id是i2c总线编号。
使用完要释放:
void i2c_put_adapter(struct i2c_adapter *adap);
如果连i2c设备的地址提前都步子道,甚至在不同的板子上有不同的地址,可以提供一个地址列表供系统探测。
此时应该使用的函数是i2c_new_probe_device。用法如下:
2. static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
3. static int __devinit uio_probe(struct platform_device *pdev)
4. {
5. (...)
6. struct i2c_adapter *i2c_adap;
7. struct i2c_board_info i2c_info;
8. (...)
9. i2c_adap = i2c_get_adapter(2);
10. memset(&i2c_info, 0, sizeof(struct i2c_board_info));
11. strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
12. isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
13. normal_i2c);
14. i2c_put_adapter(i2c_adap);
15. (...)
16. }
i2c_new_probed_device的原型是:
struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info,
unsigned short const *addr_list);
这个函数将会在指定的总线上探测addr_list中的地址,将第一个有ACK反馈的地址赋给info->addr,
然后使用前两个参数调用i2c_new_device。它的返回值也是一个可用的i2c_client指针。
i2c_unregister_device() 可以注销i2c_new_device()/i2c_new_probed_device()申请的i2c_client。
补充:如何知道一个物理i2c总线的编号?
[root@zq /]# cat /sys/class/i2c-dev/i2c-0/name
PNX4008-I2C0
[root@zq /]# cat /sys/class/i2c-dev/i2c-1/name
PNX4008-I2C1
[root@zq /]# cat /sys/class/i2c-dev/i2c-2/name
USB-I2C
三、在所有i2c总线上探测特定设备。
内核文档中关于方法2的限制及方法3的好处我没看懂。说一下自己的理解,那就是方法2虽然可以探测多个地址,但是仅仅能在一个指定的总线上探测,并且探测到第一个可用的地址就停止探测了。如果之前并不确定总线的编号,或者一次探测多个i2c设备,就需要用到第三种方法了。
实现第三种方法需要两个条件:
l 实现i2c_driver的detect成员。这个成员函数原型是:
int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *);
这个函数必须检查第二个参数的addr域是否自己支持的地址,是的话则至少填充info->type,info的其它成员也可以填充,但不应该修改addr。如果是就返回0,否则返回-ENODEV。
l 初始化i2c_driver的address_list成员。i2c_driver注册的时候,i2c_core会在所有已经注册的i2c_adapter上探测address_list中的所有地址,硬件探测成功之后后调用i2c_driver的detect成员,然后根据detect填充的info建立一个i2c_client。如果两个总线上有相同的地址的设备,那么会分别建立两个i2c_client。如果address_list中的多个地址都有设备占用,那么会建立多个i2c_client。
但实际上,内核文档不推荐这种方法,而是优先选用方法1和2,可能是因为这种方法过于灵活。
四、从用户空间枚举。
如果编写驱动之前确实无法得知i2c设备的地址(甚至连地址列表都不得而知),那就需要系统运行后从用户空间输入了。
用户空间通过两个sysfs属性文件来建立和删除i2c_client:new_device和delete_device。这两个文件都是只写的。
new_device有两个参数:i2c设备的名字(字符串)和地址(以0x开头的16进制数)。delete_device只有一个参数,那就是设备的地址。
举例说明:
# echo device-name 0x50 > /sys/bus/i2c/devices/i2c-3/new_device
可以看到,此时已经指定了总线编号。
(更详细的内容请参看kernel文档噢)O(∩_∩)O
如何实例化i2c_client(四法)的更多相关文章
- Linux I2C(一)之常用的几种实例化(i2c_client ) 【转】
转自:http://blog.csdn.net/lugandong/article/details/48092397 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 前言 方式 ...
- Linux kernel中断子系统之(五):驱动申请中断API【转】
转自:http://www.wowotech.net/linux_kenrel/request_threaded_irq.html 一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的 ...
- i2c_client 几种实例化方法
http://blog.csdn.net/lugandong/article/details/48092397
- i2c_client的生成
网上很多文档都是介绍源码,包括i2c_client结构体的源码都有贴出,看上去似乎需要手动写该结构体,但实际上,i2c_client的生成是用如下方法. \arch\arm\mach-omap2/bo ...
- linux I2C_client产生方法一
\arch\arm\mach-omap2/board-am335xevm.c static struct i2c_board_info am335x_i2c2_boardinfo[] = { { I ...
- Spring中Bean的实例化
Spring中Bean的实例化 在介绍Bean的三种实例化的方式之前,我们首先需要介绍一下什么是Bean,以及Bean的配置方式. 如果 ...
- [转]ThinkPHP中实例化对象M()和D()的区别,select和find的区别
1.ThinkPHP中实例化对象M()和D()的区别 在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法实例化模型无需用户为每个数据表定义模型类,如果D方法没有找到定义的模型类,则会 ...
- 对C#泛型实例化对像
public class A { } public class B<T> { public static T Get() { //在这一块如何实例化T这个对象呢?如果用default(T) ...
- spring实例化bean的三种方式
公共使用的实体
随机推荐
- 数据库(MSSQLServer,Oracle,DB2,MySql)常见语句以及问题(续1之拼接字符串)
上一篇文章http://www.cnblogs.com/valiant1882331/p/4056403.html写的太长了,所以就换了一篇,链接上一节继续 字符串的拼接 MySql中可以使用&quo ...
- CSS禁止Chrome谷歌浏览器激活输入框后自动添加橘黄色边框
Chrome默认会为所有的输入框加上橘黄色的边框,虽然有时候可以使我们的网站看起来更友好,但对自定义的样式是有影响的.当鼠标点击输入框时,在谷歌chrome浏览器中,光标移到输入框时激活输入框会被加上 ...
- javascript进阶——面向对象特性
面向对象的javascript是这门语言被设计出来时就考虑的问题,熟悉OOP编程的概念后,学习不同的语言都会发现不同语言的实现是不同的,javascript的面向对象特性与其他具有面向对象特性的语言的 ...
- 在ubuntu12.0.4上搭建samba服务器以实现文件共享
在安装之前samba服务器之前,先进行以下配置和测试. <壹> 准备工作 一.NAT联网方式 (1)硬件连接 无需网线,无需路由器 (2)虚拟机选择NAT连接方式 (3)测试网络通不通 在 ...
- c++ 最短路两种算法
最短路是个老问题了,大神们留下很多文档但是很多都是针对算法使用一些固定大小的数组进行数据存储在实际应用中受到限制,这里自己练习一下,主要用了一些c++的stl,减少了固定长度数组的依赖,换一种写法试图 ...
- 这是从word发的第一篇博客。
喜欢做的事,怎么样都不会厌倦. 以前只知道office功能强大,但不太清楚到底还能干些啥,印象最深的是outlook了,自己也在用,挺好 今天偶然发现,word还能发布博客,真是太惊喜了 这算是一篇实 ...
- Uva10207 The Unreal Tournament
题目链接戳这里 首先递归调用函数次数其实是可以预处理出来的,但是这里我们介绍一个更屌的做法. 设\(F(i,j)\)为求解\(P(i,j)\)所遍历的节点数目,则有\[F(0,j)=F(i,0)=0\ ...
- [原博客] POJ 1067 取石子游戏
题目链接有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者 ...
- Kaggle Competition Past Solutions
Kaggle Competition Past Solutions We learn more from code, and from great code. Not necessarily alwa ...
- XSS解决方案系列之四:关于编码
本文准备说明以下几个问题: 1. 关于重复编码的问题 2. 关于编码的多种形式的问题 3. 关于编码的几个常见问题 [说明] 本文所述编码是指encode,可以理解为转义,而不是编程序写代码. 编码或 ...