Linux2.6.30/driver/i2c/
1.algos: 协议算法相关的东西
2.busses: 各种平台的i2c总线驱动(i2c控制器驱动/i2c适配器驱动)
3.chips: 各种i2c设备驱动(e2prom/某种传感器/触摸屏)
4.i2c-core.c i2c-dev.c: i2c子系统的通用文件(i2c核心层,提供一些通用函数接口)
应用层app: open("设备文件") write read
====================================================================
内核的核心部分 VFS:sys_open sys_write sys_read
向上提供操作驱动的接口: 1.申请主设备号,注册通用接口 register——chrdev
2.构建file_operations结构体
.open
.write -->利用子系统核心层的函数来找到下层的操作方法
.read
(工作层) 3.i2c设备驱动层(e2prom驱动/触摸屏驱动/传感器驱动) :提供策略
2.i2c核心层(i2c-core.c)提供一些通用函数接口,提供了注册/注销的方法
1.i2c总线驱动层(i2c控制器驱动/i2c适配器驱动) :提供操作一个硬件的能力
做准备工作--》1.构建一个适配器结构体struct i2c_adapter(用来描述一个i2c设备)
1. 成员:任何一个控制器都应该有套算法
const struct i2c_algorithm *algo;
2. 任何一套算法都应该有一套函数来实现
*master_xfer //实现这个函数--》实现读写操作方法
2.初始化控制器--》会用到平台设备驱动机制
3.注册到子系统当中去 i2c_add_adapter
======================================================================
硬件: i2c控制器设备
||
\/
i2c设备(e2prom)
应用层app: open("设备文件") write read
====================================================================
VFS:sys_open sys_write sys_read
1.i2c设备驱动: 两种写法 (1)万能接口驱动(i2c-dev.c)
(2)e2prom驱动、传感器驱动
1.构建file_operations结构体
.open
.write
.read
2.创建设备文件
kernel:
驱动: 2.i2c核心层
3.i2c总线驱动
===========================================================================
i2c控制器
e2prom 传感器
i2c-dev.c文件分析:
==========================================================
static struct i2c_driver i2cdev_dirver = {
.driver = {
.name = "dev_driver",
},
.attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter,
};
入口函数:
i2c_dev_init
/*注册*/
1.register_chrdev();
/*创建一个类*/
2.class_create();
/*加载i2c驱动*/
3.i2c_add_driver();
1.加载i2c设备驱动结构体,加载到一个链表中
2.搜索i2c_adapter链表,每搜索一个都会调用.attach_adapter
i2cdev_attach_adapter 函数分析:
===========================================open("dev/i2c-1");
创建一个设备文件
1.device_create(); //底层有几个i2c适配器就会创建几个设备文件,而且创建的设备文件名为:i2c-0,i2c-1 ...
如何来用i2c通用接口驱动
=================================================
open
sys_open
file_operations--> i2cdev_fops.open = i2cdev_open
/*1.获取次设备号*/
unsigned int minor = iminor(inode);
/*2.创建三个结构体*/
struct i2c_client *client;
struct i2c_adapter *adap;
struct i2c_dev *i2c_dev;
/*3.获取i2c_dev*/
i2c_dev = i2c_dev_get_by_minor();
/*4.获取i2c配置*/
adap = i2c_get_adapter();
/*5.设置i2c-client*/
client->adapter = adap;
file->private_data = client;
ioctl(fd, I2C_SLAVE, addr)
sys_ioctl
file_operations --> i2cdev_fops.ioctl = i2cdev_ioctl
/*1.从file->private_data里面取出i2c_client*/
struct i2c_client *client = (struct i2c_client *)file->private_data;
case I2C_SLAVE:
client->addr = arg;
write
sys_write
file_operations--> i2cdev_fops.write = i2cdev_write //i2c设备层
/*1.从file->private_data里面取出i2c_client*/
struct i2c_client *client = (struct i2c_client *)file->private_data;
/*2.发送数据*/
ret = i2c_master_send(); //开始进入i2c核心层
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg; //构建一个写消息结构体
msg.addr = client->addr; //上面ioctl写入
msg.flags = client->flags *I2C_M_TEN;
msg.len = count;
msg.buf = (char *)buf;
/*转接到底层的函数*/
i2c_transfer();
adap->algo->master_xfer(); //开始进入总线驱动层
read
sys_read
file_operations--> i2cdev_fops.read = i2cdev_read //i2c设备层
/*1.从file->private_data里面取出i2c_client*/
struct i2c_client *client = (struct i2c_client *)file->private_data;
tmp = kmalloc(count, GFP_KERNEL);
ret = i2c_master_recv();
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg; //构建一个写消息结构体
msg.addr = client->addr; //上面ioctl写入
msg.flags = client->flags *I2C_M_TEN;
msg.flags |= I2C_M_RD; //将标记改为读
msg.len = count;
msg.buf = (char *)buf;
copy_to_user(buf, tmp, count);
i2c子系统涉及的函数接口与重要结构体
===================================================================
1.struct i2c_driver //描述一个i2c设备驱动
2.struct i2c_adapter //描述一个i2c控制器/i2c适配器
3.struct i2c_client *client; //描述一个i2c设备(如:e2prom)
.addr = 0xa0
.adapter =
.driver
4.struct i2c_msg //描述一个i2c消息
.__u16 addr; /*器件地址*/
.__u16 flags; /*要读还是写*/0:写 1:读
.__u16 len; /*数据长度*/
.__u8 *buf; /*要写入的数据,或者读出来的数据放在这里*/
函数接口:
1.i2c_add_driver //加载i2c设备驱动结构体,加载到一个链表里面
2.i2c_add_adapter //加载i2c适配器结构体到适配器链表
3.i2c_master_send //发送数据函数
4.i2c_transfer; //转接到底层的函数