如何实例化i2c_client(四法)

时间:2022-09-08 12:38:16

一、在板文件进行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);// idi2c总线编号。

使用完要释放:

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(四法)的更多相关文章

  1. Linux I2C(一)之常用的几种实例化(i2c_client ) 【转】

    转自:http://blog.csdn.net/lugandong/article/details/48092397 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 前言 方式 ...

  2. Linux kernel中断子系统之(五):驱动申请中断API【转】

    转自:http://www.wowotech.net/linux_kenrel/request_threaded_irq.html 一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的 ...

  3. i2c_client 几种实例化方法

    http://blog.csdn.net/lugandong/article/details/48092397

  4. i2c_client的生成

    网上很多文档都是介绍源码,包括i2c_client结构体的源码都有贴出,看上去似乎需要手动写该结构体,但实际上,i2c_client的生成是用如下方法. \arch\arm\mach-omap2/bo ...

  5. linux I2C_client产生方法一

    \arch\arm\mach-omap2/board-am335xevm.c static struct i2c_board_info am335x_i2c2_boardinfo[] = { {  I ...

  6. Spring中Bean的实例化

                                    Spring中Bean的实例化 在介绍Bean的三种实例化的方式之前,我们首先需要介绍一下什么是Bean,以及Bean的配置方式. 如果 ...

  7. [转]ThinkPHP中实例化对象M()和D()的区别,select和find的区别

    1.ThinkPHP中实例化对象M()和D()的区别 在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法实例化模型无需用户为每个数据表定义模型类,如果D方法没有找到定义的模型类,则会 ...

  8. 对C#泛型实例化对像

    public class A { } public class B<T> { public static T Get() { //在这一块如何实例化T这个对象呢?如果用default(T) ...

  9. spring实例化bean的三种方式

    公共使用的实体

随机推荐

  1. 【AutoMapper官方文档】DTO与Domin Model相互转换(上)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

  2. UML状态图和活动图

    UML状态图和活动图 统一建模语言UML(Unified Modeling Language)是非专利的第三代建模和规约语言.UML是一种开放的方法,用于说明.可视化.构建和编写一个正在开发的.面向对 ...

  3. Counterfeit Dollar 分类: POJ 2015-06-12 15&colon;28 19人阅读 评论&lpar;0&rpar; 收藏

    Counterfeit Dollar Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 41559   Accepted: 13 ...

  4. PHP中关于超链接的拼接问题

    <?php$link = " http://www.baidu.com";echo '<a href='.$link.'> 百度 </a>';?&gt ...

  5. USB HID报告及报告描述符简介

    在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报告描述符(Report Descriptor)是HID ...

  6. LCD驱动移植在在mini2440&lpar;linux2&period;6&period;29&rpar;和FS4412&lpar;linux3&period;14&period;78&rpar;上实现对比(deep dive)

    1.Linux帧缓冲子系统 帧缓冲(FrameBuffer)是Linux为显示设备提供的一个接口,用户可以将帧缓冲看成是显示内存的一种映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作 ...

  7. Linux搭建lamp&lpar;Apache&plus;PHP&plus;Mysql环境&rpar;centos7&period;2版详细教程

    我们更多的网站服务器是选择了Linux系统,这里建议你选择centos,这也是阿里云ecs推荐的系统,在服务器上比较推荐centos,特别对于新手,首选CentOS,并不是centos比Debian和 ...

  8. 一&colon; WCF的服务端与客户端在通信时有三种模式:请求响应模式、数据报模式和双工通讯模式。

    说一下基本知识,  1.如果想要将当前接口作为wcf服务器,则一定要加上[ServiceContract] 契约 2.要想将方法作为wcf服务方法发布给外部调用,则一定要加上    [Operatio ...

  9. at用法小记

    By francis_hao    Aug 22,2017   at – 设置稍后执行的作业. 概要 at [-V] [-f file] [-mMlv] timespec...at [-V] [-f ...

  10. 【HDOJ5981】Guess the number(DP)

    题意:A和B玩一个游戏:A在[L,R]之间随机选取一个数X,之后由B来猜这个数, 如果猜的数比X小,则A就告诉B你猜的数小了, 如果猜的数等于X则游戏结束, 如果猜的数大于X,则在这之后A只会回答B是 ...