1.i2c-dev.c(i2c设备驱动组件层)
功能:1)给用户提供接口
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)提供基本的接口函数,用来建立上层与下层的连接 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.c
功能:1)实现对i2c控制器的初始化 2)实现操作方法(实现i2c协议,完成数据的发送)
如何用通用接口驱动来操作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
@成鹏致远
(blogs:http://lcw.cnblogs.com)
(email:wwwlllll@126.com)
(qq:552158509)