1 分析i2c设备的识别过程
i2c_add_driver
    i2c_register_driver
        driver->driver.bus = &i2c_bus_type;
        driver_register(&driver->driver);
        
        list_for_each_entry(adapter, &adapters, list) {
            driver->attach_adapter(adapter);
                        i2c_probe(adapter, &addr_data, eeprom_detect);
                            i2c_probe_address // 发出S信号,发出设备地址(来自addr_data)
                                i2c_smbus_xfer
                                    i2c_smbus_xfer_emulated
                                        i2c_transfer
                                            adap->algo->master_xfer // s3c24xx_i2c_xfer
                                            
        
2 怎么写I2C设备驱动程序?
2.1 分配一个i2c_driver结构体
2.2 设置
      attach_adapter // 它直接调用 i2c_probe(adap, 设备地址, 发现这个设备后要调用的函数);
      detach_client  // 卸载这个驱动后,如果之前发现能够支持的设备,则调用它来清理
      
2.3 注册:i2c_add_driver

3 写代码

 #include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <asm/uaccess.h> static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; /* 地址值是7位 */
/* 改为0x60的话, 由于不存在设备地址为0x60的设备, 所以at24cxx_detect不被调用 */ static unsigned short force_addr[] = {ANY_I2C_BUS, 0x60, I2C_CLIENT_END};
static unsigned short * forces[] = {force_addr, NULL}; static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr, /* 要发出S信号和设备地址并得到ACK信号,才能确定存在这个设备 */
.probe = ignore,
.ignore = ignore,
//.forces = forces, /* 强制认为存在这个设备 */
}; static struct i2c_driver at24cxx_driver; static int major;
static struct class *cls;
struct i2c_client *at24cxx_client; static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
{
unsigned char address;
unsigned char data;
struct i2c_msg msg[];
int ret; /* address = buf[0]
* data = buf[1]
*/
if (size != )
return -EINVAL; copy_from_user(&address, buf, ); /* 数据传输三要素: 源,目的,长度 */ /* 读AT24CXX时,要先把要读的存储空间的地址发给它 */
msg[].addr = at24cxx_client->addr; /* 目的 */
msg[].buf = &address; /* 源 */
msg[].len = ; /* 地址=1 byte */
msg[].flags = ; /* 表示写 */ /* 然后启动读操作 */
msg[].addr = at24cxx_client->addr; /* 源 */
msg[].buf = &data; /* 目的 */
msg[].len = ; /* 数据=1 byte */
msg[].flags = I2C_M_RD; /* 表示读 */ ret = i2c_transfer(at24cxx_client->adapter, msg, );
if (ret == )
{
copy_to_user(buf, &data, );
return ;
}
else
return -EIO;
} static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
unsigned char val[];
struct i2c_msg msg[];
int ret; /* address = buf[0]
* data = buf[1]
*/
if (size != )
return -EINVAL; copy_from_user(val, buf, ); /* 数据传输三要素: 源,目的,长度 */
msg[].addr = at24cxx_client->addr; /* 目的 */
msg[].buf = val; /* 源 */
msg[].len = ; /* 地址+数据=2 byte */
msg[].flags = ; /* 表示写 */ ret = i2c_transfer(at24cxx_client->adapter, msg, );
if (ret == )
return ;
else
return -EIO;
} static struct file_operations at24cxx_fops = {
.owner = THIS_MODULE,
.read = at24cxx_read,
.write = at24cxx_write,
}; static int at24cxx_detect(struct i2c_adapter *adapter, int address, int kind)
{
printk("at24cxx_detect\n"); /* 构构一个i2c_client结构体: 以后收改数据时会用到它 */
at24cxx_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
at24cxx_client->addr = address;
at24cxx_client->adapter = adapter;
at24cxx_client->driver = &at24cxx_driver;
strcpy(at24cxx_client->name, "at24cxx");
i2c_attach_client(at24cxx_client); major = register_chrdev(, "at24cxx", &at24cxx_fops); cls = class_create(THIS_MODULE, "at24cxx");
class_device_create(cls, NULL, MKDEV(major, ), NULL, "at24cxx"); /* /dev/at24cxx */ return ;
} static int at24cxx_attach(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, at24cxx_detect);
} static int at24cxx_detach(struct i2c_client *client)
{
printk("at24cxx_detach\n");
class_device_destroy(cls, MKDEV(major, ));
class_destroy(cls);
unregister_chrdev(major, "at24cxx"); i2c_detach_client(client);
kfree(i2c_get_clientdata(client)); return ;
} /* 1. 分配一个i2c_driver结构体 */
/* 2. 设置i2c_driver结构体 */
static struct i2c_driver at24cxx_driver = {
.driver = {
.name = "at24cxx",
},
.attach_adapter = at24cxx_attach,
.detach_client = at24cxx_detach,
}; static int at24cxx_init(void)
{
i2c_add_driver(&at24cxx_driver);
return ;
} static void at24cxx_exit(void)
{
i2c_del_driver(&at24cxx_driver);
} module_init(at24cxx_init);
module_exit(at24cxx_exit); MODULE_LICENSE("GPL");

i2c设备驱动程序

驱动13.i2c设备驱动程序的更多相关文章

  1. 驱动05.lcd设备驱动程序

    参考s3c2410fb.c总结出框架 1.代码分析 1.1 入口函数 int __devinit s3c2410fb_init(void) { return platform_driver_regis ...

  2. linux设备驱动程序-i2c(0)-i2c设备驱动源码实现

    (基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...

  3. linux设备驱动程序-i2c(1):i2c总线的添加与实现

    linux设备驱动程序-i2c(1):i2c总线的添加与实现 (基于4.14内核版本) 在上一章节linux设备驱动程序-i2c(0)-i2c设备驱动源码实现中,我们演示了i2c设备驱动程序的源码实现 ...

  4. linux设备驱动程序--串行通信驱动框架分析

    linux 串行通信接口驱动框架 在学习linux内核驱动时,不论是看linux相关的书籍,又或者是直接看linux的源码,总是能在linux中看到各种各样的框架,linux内核极其庞杂,linux各 ...

  5. Linux驱动之I2C总线设备以及驱动

    [ 导读] 本文通过阅读内核代码,来梳理一下I2C子系统的整体视图.在开发I2C设备驱动程序时,往往缺乏对于系统整体的认识,导致没有一个清晰的思路.所以从高层级来分析一下I2C系统的设计思路,将有助于 ...

  6. 乾坤合一~Linux设备驱动之I2C核心、总线以及设备驱动

    我思念的城市已是黄昏 为何我总对你一往情深 曾经给我快乐 也给我创伤 曾经给我希望 也给我绝望 我在遥远的城市 陌生的人群 感觉着你遥远的忧伤 我的幻想 你的忧伤,像我的的绝望,那样漫长,,,,,这是 ...

  7. Linux 驱动框架---i2c驱动框架

    i2c驱动在Linux通过一个周的学习后发现i2c总线的驱动框架还是和Linux整体的驱动框架是相同的,思想并不特殊比较复杂的内容如i2c核心的内容都是内核驱动框架实现完成的,今天我们暂时只分析驱动开 ...

  8. linux驱动之I2C

    include/linux/i2c.h struct i2c_msg;struct i2c_algorithm;struct i2c_adapter;struct i2c_client;struct ...

  9. Linux I2C设备驱动编写(二)

    在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c_client.三者的关系也在上一节进行了描述.应该已经算是对Linux I2C子系统有了初步 ...

随机推荐

  1. JQuery图片轮播实例

    HTML+CSS代码: <!doctype html> <html> <head> <meta charset="utf-8"> & ...

  2. CentOS 7 忘记root密码解决方法

    CentOS 7  root密码的重置方式和CentOS 6完全不一样,CentOS 7与之前的版本6变化还是比较大的,以进入单用户模式修改root密码为例: 1.重启机器,进入grub菜单的时候按e ...

  3. Python基础(六)——面向对象编程

    (1)定义类和实例 这一部分难得和 Java 较为一致,直接写个例子: class Stu: def __init__(self, name, id): # 构造方法 self.name = name ...

  4. OpenCV中图像的BGR格式及Img对象的属性说明

    1. 图像的BGR格式说明 OpenCV中图像读入的数据格式是numpy的ndarray数据格式.是BGR格式,取值范围是[0,255]. 如下图所示,分为三个维度: 第一维度:Height 高度,对 ...

  5. 图上两点之间的第k最短路径的长度 ACM-ICPC 2018 沈阳赛区网络预赛 D. Made In Heaven

    131072K   One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. Howe ...

  6. Leetcode 145. 二叉树的后序遍历

    题目链接 https://leetcode-cn.com/problems/binary-tree-postorder-traversal/description/ 题目描述 给定一个二叉树,返回它的 ...

  7. lwqq

    源码安装lwqq 加密保存密码 发送截图

  8. Linux学习-什么是 daemon 与服务 (service)

    『常驻在记体体中的程序,且可以提供 一些系统或网络功能,那就是服务』.而服务一般的英文说法是『 service 』. 那么 daemon 与 service 有关啰?否则为什么都能够提供 某些系统或网 ...

  9. Java技术——多态的实现原理

    .方法表与方法调用 如有类定义 Person, Girl, Boy class Person { public String toString(){ return "I'm a person ...

  10. 光学字符识别OCR-7语言模型

    由于图像质量等原因,性能再好的识别模型,都会有识别错误的可能性,为了减少识别错误率,可以将识别问题跟统计语言模型结合起来,通过动态规划的方法给出最优的识别结果.这是改进OCR识别效果的重要方法之一. ...