S3C2440驱动简析——I2C驱动(3)

     书接上回,在讨论完i2c设备、i2c适配器等初始化和删除相应驱动的程序后,我们在这个小节把注意力放在file_operations里面的几个函数操作上,先贴上file_operations结构体代码,让我们先看看其包含了哪几个函数。

 

 

这个结构体想必大家对其结构都相当清晰啦,由此可见,i2c驱动为用户空间提供的操作函数包括:

1.no_llseek

2.i2cdev_read

3.i2cdev_write

4.i2cdev_ioctl

5.i2cdev_open

6.i2cdev_release

 

下面就对它们逐一进行分析:

1.no_llseek

从结构体i2cdev_fops 的成员名字llseek推测,其作用应该是改变当前I2C器件读写的位置,而现在正如大家所见,驱动程序并未实现这功能。

 

 

2.i2cdev_read

 

read函数主要做的事情有:

(1)struct i2c_client *client = file->private_data;

       通过参数传入的file(在上一篇博文有阐述)而找到像对应的一个i2c设备,接下来函数就是对该设备进行操作。

(2)ret = i2c_master_recv(client, tmp, count);

       其中i2c_master_recv函数在i2c-core.c 中实现,为了使本文结构更加清晰,故把跟硬件打交道的代码文件i2c-core.c 放在后面的博文分析。在这里,我们只需简单地理解为i2c_master_recv函数的作用是通过调用上文提及的i2c设备,并从其中提取count 字节的内容存到tmp 缓冲区里。

(3)ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;

       若无异常情况发生,就会调用咱们非常熟悉的copy_to_user 函数,这个函数在这里就不赘述了,建议还没掌握的朋友查找相关资料,或者我前面的博文都有提及过,这个是基础吖!

 

 

3.i2cdev_write

 

write函数又做了什么事情呢?

(1)struct i2c_client *client = file->private_data;

       见上文read函数中的解释。

(2)tmp = memdup_user(buf, count);

       memdup_user 函数在Util.c 中实现,源代码如下

      

      函数的作用一目了然,就是把指针src 所指向长度为len 的内容中copy_from_user 到函数返回的指针。

(3)ret = i2c_master_send(client, tmp, count);

       把缓存器tmp 里的内容发送到设备client 。

 

 

4.i2cdev_ioctl

 

由于i2c适配器的设备节点代表的是整条i2c总线,所以在对其进行具体的文件系统操作之前还必须指明
待访问设备的总线地址。指明地址的操作通过ioctl 系统调用完成的,它最终调用设备方法i2cdev_ioctl。ioctl函数还是采用我们非常熟悉的switch-case逻辑结构,其各种命令对应的操作分析如下

case I2C_SLAVE:
case I2C_SLAVE_FORCE: 设置从设备地址

 

case I2C_TENBIT: 设置7bit 地址 or 10bit 地址

 

case I2C_PEC: 如果I2C_PEC != 0 , to use PEC with SMBus

 

case I2C_FUNCS: 返回控制器算法所支持的传输种类

 

case I2C_RDWR: 执行i2cdev_ioctl_rdrw函数,代码如下

整个函数主要做了以下几件事

(1)copy_from_user(&rdwr_arg,
                              (struct i2c_rdwr_ioctl_data __user *)arg,
                              sizeof(rdwr_arg))

       获得用户传进来的命令,并存放在rdwr_arg。

(2)copy_from_user(rdwr_pa, rdwr_arg.msgs,
                              rdwr_arg.nmsgs * sizeof(struct i2c_msg))

       把指针rdwr_pa指向结构体rdwr_arg的成员msgs。

(3)整个for循环实质就是把要进行传输的每个msg的信息copy到字符串指针data_ptrs当中。

(4)res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);

       i2c_transfer ()函数用于进行I2C适配器和I2C设备之间的一组消息交互,i2c_transfer()函数本身不具备驱动适配器物理硬件完成消息交互的能力,它只是寻找到i2c_adapter对应的i2c_algorithm,并使用i2c_algorithmmaster_xfer()函数真正驱动硬件流程。至于i2c_algorithm和master_xfer等在接下来的博文介绍。

(5)while循环里把data_ptrs所存的信息统统copy_to_user。

case I2C_SMBUS: 执行i2cdev_ioctl_smbus 函数,主要调用i2c_smbus_xfer,函数在i2c-core.c 里实现。在这里我们先简单理解此函数作用为选择smbus 通信协议。

case I2C_RETRIES: 设置重发次数

case I2C_TIMEOUT: 设置超时时间,设定为 arg * 10 (ms)

呼呼~ioctl函数总算带过了,具体没有深入的地方,均是涉及到i2c-core.c 和数据结构i2c_algorithm的地方,这两个东东留待接下来的博文再来收拾。

5.i2cdev_open

最后两个函数来点轻松的,一眼扫下来,就是一些注册、初始化等工作,唯一要注意地方是这个open函数比之前所介绍的其他驱动多了一点绑定的工作,如:

client->driver = &i2cdev_driver;

client->adapter = adap;
file->private_data = client;

至于其用意,不记得的朋友建议翻看本i2c驱动系列的第一篇博文。

 

6.i2cdev_release

对照着open函数来看,这个release岂不是小菜一碟?

 

 

 

    到此为止,i2c-dev.c 的驱动代码分析暂告一段落,由于本人水平所限,不能很深刻、到位的写出这份驱动代码的分析,还请各位看客多多提点。内容错漏,请严厉指出!接下来本系列的第4篇博文将讲述i2c-core.c 和数据结构i2c_algorithm,敬请关注!

 

本系列博文链接:

I2C驱动(1)http://blog.csdn.net/jarvis_xian/archive/2011/05/27/6449939.aspx
I2C驱动(2)http://blog.csdn.net/jarvis_xian/archive/2011/05/27/6451168.aspx
I2C驱动(3)http://blog.csdn.net/jarvis_xian/archive/2011/05/28/6452431.aspx
I2C驱动(4)http://blog.csdn.net/jarvis_xian/archive/2011/05/30/6455697.aspx

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值