1.i2c-dev.c(i2c設備驅動組件層)
功能:1)給用戶提供接口app
i2c_dev_init //入口函數
/*申請主設備號*/函數
register_chrdev(I2C_MAJOR(
89),
"i2c",
&i2cdev_fops);
/*建立一個設備類*/
i2c_dev_class
= class_create(THIS_MODULE,
"i2c-dev");
/*註冊一個i2c驅動*/
i2c_add_driver(
&i2cdev_driver);
i2c_register_driver(THIS_MODULE, driver);
/*指定總線類型*/
driver
-
>driver.bus
=
&i2c_bus_type;
/*驅動註冊
*1.將i2c驅動加入i2c總線的驅動鏈表
*2.搜索設備鏈表,實現匹配,根據i2c總線的匹配原理:必需要求i2c驅動結構體中實現id_table
* 可是,i2c驅動結構體中並無實現id_table,因此永遠都匹配失敗
*/
driver_register(
&driver
-
>driver);
/*搜索適配器鏈表,每搜索一個適配器,都會調用__process_new_driver函數
*在此函數中,又會調用i2c驅動中的,attach_adapter函數
*/
bus_for_each_dev(
&i2c_bus_type, NULL, driver, __process_new_driver);
__process_new_driver
//此函數可能會被調用屢次
i2c_do_add_adapter(data, to_i2c_adapter(dev));
if (driver
-
>attach_adapter) {
/* We ignore the return code; if it fails, too bad */
driver
-
>attach_adapter(adap);
//i2cdev_attach_adapter
}
static
const
struct file_operations i2cdev_fops
= {
.owner
= THIS_MODULE,
.llseek
= no_llseek,
.read
= i2cdev_read,
.write
= i2cdev_write,
.unlocked_ioctl
= i2cdev_ioctl,
.open
= i2cdev_open,
.release
= i2cdev_release,
};
static
struct i2c_driver i2cdev_driver
= {
.driver
= {
.name
=
"dev_driver",
},
.attach_adapter
= i2cdev_attach_adapter,
.detach_adapter
= i2cdev_detach_adapter,
};
2.i2c-core.c(i2c核心層組件)
功能:1)註冊一條i2c總線
2)提供基本的接口函數,用來創建上層與下層的鏈接this
i2c_init
//入口函數
/*註冊I2C總線*/
bus_register(
&i2c_bus_type);
struct bus_type i2c_bus_type
= {
//實際的物理總線,I2C總線
.name
=
"i2c",
.match
= i2c_device_match,
//匹配函數
.probe
= i2c_device_probe,
.remove
= i2c_device_remove,
.shutdown
= i2c_device_shutdown,
.pm
=
&i2c_device_pm_ops,
};
static
int i2c_device_match(
struct device
*dev,
struct device_driver
*drv)
{
struct i2c_client
*client
= i2c_verify_client(dev);
struct i2c_driver
*driver;
if (
!client)
return
0;
driver
= to_i2c_driver(drv);
/* match on an id table if there is one */
if (driver
-
>id_table)
return i2c_match_id(driver
-
>id_table, client)
!= NULL;
while (id
-
>name[
0]) {
if (strcmp(client
-
>name, id
-
>name)
==
0)
return id;
id
++;
}
return
0;
}
涉及的重要結構體:
struct i2c_client {
//表示一個i2c設備
unsigned
short flags;
/* div., see below */
unsigned
short addr;
/*器件地址*/
char name[I2C_NAME_SIZE];
/*名字*/
struct i2c_adapter
*adapter;
/*所屬適配器,所屬控制器*/
struct i2c_driver
*driver;
/*設備驅動*/
struct device dev;
/* the device structure */
int irq;
/* irq issued by device */
struct list_head detected;
};
struct i2c_driver {
//用來表示i2c驅動
unsigned
int
class;
/* Notifies the driver that a new bus has appeared or is about to be
* removed. You should avoid using this if you can, it will probably
* be removed in a near future.
*/
int (
*attach_adapter)(
struct i2c_adapter
*);
int (
*detach_adapter)(
struct i2c_adapter
*);
/*probe函數:初始化工做,設備檢測,*/
int (
*probe)(
struct i2c_client
*,
const
struct i2c_device_id
*);
int (
*remove)(
struct i2c_client
*);
struct device_driver driver;
//設備驅動
const
struct i2c_device_id
*id_table;
//指定此驅動能爲哪些設備服務
...
...
};
struct i2c_adapter {
//表示一個i2c適配器/i2c控制器
const
struct i2c_algorithm
*algo;
/* the algorithm to access the bus */
/*操做方法*/
int (
*master_xfer)(
struct i2c_adapter
*adap,
struct i2c_msg
*msgs,
int num);
int nr;
/*適配器的號碼*/
...
...
};
struct i2c_msg {
//表示一個i2c數據包
__u16 addr;
/*設備地址*/
__u16 flags;
/*表示:1-表示讀包 0-表示寫包*/
__u16 len;
/*數據包的長度*/
__u8
*buf;
/*真正的數據*/
...
...
};
涉及的重要函數接口:
/*註冊一個i2c控制器*/
int i2c_add_adapter(
struct i2c_adapter
*adapter)
int i2c_del_adapter(
struct i2c_adapter
*adap)
/*註冊i2c驅動*/
int i2c_add_driver(
struct i2c_driver
*driver)
int i2c_add_numbered_adapter(
struct i2c_adapter
*adap)
int i2c_del_numbered_adapter(
struct i2c_adapter
*adap)
extern
int i2c_del_driver(
struct i2c_driver
*driver);
/*接收i2c數據包*/
int i2c_master_recv(
struct i2c_client
*client,
char
*buf,
int count)
/*發送i2c數據包*/
int i2c_master_send(
struct i2c_client
*client,
const
char
*buf,
int count)
/*提交i2c數據包到總線驅動層*/
int i2c_transfer(
struct i2c_adapter
*adap,
struct i2c_msg
*msgs,
int num)
3.busses目錄:i2c總線驅動/i2c控制器驅動/i2c適配器驅動
i2c-s3c2410.cspa
功能:1)實現對i2c控制器的初始化
2)實現操做方法(實現i2c協議,完成數據的發送)code
如何用通用接口驅動來操做i2c設備
open
app
: open(
"/dev/i2c-0", O_RDWR);
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
=
sys
: sys_open
...
...
i2c
-dev.c
struct file_operations i2cdev_fops
.open
= i2cdev_open,
/*構建一個i2c_client*/
struct i2c_client
*client;
struct i2c_adapter
*adap;
/*獲取適配器*/
adap
= i2c_get_adapter(i2c_dev
-
>adap
-
>nr);
client
= kzalloc(
sizeof(
*client), GFP_KERNEL);
client
-
>driver
=
&i2cdev_driver;
//指定i2c設備驅動
client
-
>adapter
= adap;
//指定適配器
file
-
>private_data
= client;
ioctl
app
: ioctl(fd, I2C_SLAVE, 0x48)
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
sys
: sys_ioctl
...
...
i2c
-dev.c
struct file_operations i2cdev_fops
.unlocked_ioctl
= i2cdev_ioctl,
/*獲取i2c_client*/
struct i2c_client
*client
= file
-
>private_data;
switch (cmd) {
case I2C_SLAVE
: I2C_M_TEN
:是否爲
10位尋址的設備
if ((arg
> 0x3ff)
||(((client
-
>flags
& I2C_M_TEN)
==
0)
&& arg
> 0x7f))
return
-EINVAL;
client
-
>addr
= arg;
//0x48
}
write
app
: write(fd, wbuf,
1)
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
=
sys
: sys_write
...
...
i2c
-dev.c
struct file_operations i2cdev_fops
.write
= i2cdev_write,
/*獲取i2c_client*/
struct i2c_client
*client
= file
-
>private_data;
char
*tmp;
tmp
= kmalloc(count, GFP_KERNEL);
copy_from_user(tmp, buf, count)
/*發送數據到核心層*/
i2c
-core.c i2c_master_send(client, tmp, count);
struct i2c_msg msg;
//表示i2c數據包
/*填充數據包*/
msg.addr
= client
-
>addr;
//0x48
msg.flags
= client
-
>flags
& I2C_M_TEN;
//寫
msg.len
= count;
//1
msg.buf
= (
char
*)buf;
//wbuf 0x0
/*提交數據給總線驅動層*/
i2c_transfer(adap,
&msg,
1);
if (adap
-
>algo
-
>master_xfer)
i2c_s3c2410.c adap
-
>algo
-
>master_xfer(adap, msgs, num);
//s3c24xx_i2c_xfer
s3c24xx_i2c_xfer
@成鵬致遠blog
(blogs:http://lcw.cnblogs.com)接口
(email:wwwlllll@126.com)rem
(qq:552158509)get