(先写后读)需要在一个 io ctrl 中处理完毕 6 用户接口层-I2C 设备驱动 6.1 统一的设备
模型 此驱动模型是针对 I2C 控制器的,因为对 I2C slave 的寻址是通过报文的内容来实现的,
而对于 I2C 控制器来说,slave 的地址仅仅是某个具体的报文而已,对控制器来说是透明的,
因此用户空间访问的设备本质上就是 I2C 控制器。 6.1.1 关键数据结构 550static struct
i2c_driver i2cdev_driver = { 551 .driver = { 552 .name = "dev_driver", 553
}, 554 .id = I2C_DRIVERID_I2CDEV, 555 .attach_adapter =
i2cdev_attach_adapter, 556 .detach_adapter = i2cdev_detach_adapter, 557 .detach_clien
t = i2cdev_detach_client, 558}; 定 义 了 一个 标 准的 i2c_driver 。 41/* 42 * An i2c_dev
represents an i2c_adapter ... an I2C or SMBus master, not a 43 * slave (i2c_client) with which
messages will be exchanged. It's coupled 44 * with a character special file which is accessed by
user mode drivers. 45 * 46 * The list of i2c_dev structures is parallel to the i2c_adapter lists 47
* maintained by the driver model, and is updated using notifications 48 * delivered to the
i2cdev_driver. 49 */ 50struct i2c_dev { 51 struct list_head list; 52 struct i2c_adapter
*adap; 53 struct device *dev; 54}; 55 56#define I2C_MINORS 256 57static
LIST_HEAD(i2c_dev_list); 58static DEFINE_SPINLOCK(i2c_dev_list_lock); 定 义 了 一 个
i2c_dev 列 表 , 每 个 adapter 对 应 一 个 i2c_dev 。 478static const struct file_operations
i2cdev_fops = { 479 .owner = THIS_MODULE, 480 .llseek = no_llseek,
481 .read = i2cdev_read, 482 .write = i2cdev_write, 483 .ioctl =
i2cdev_ioctl, 484 .open = i2cdev_open, 485 .release = i2cdev_release, 486};
487 任意一个需要和用户空间通信的驱动必备的数据结构,其定义了具体的读写操作方法。
6.1.2 初始化 http://lxr.linux.no/#linux+v2.6.25/drivers/i2c/i2c-dev.c#L607 566static int __init
i2c_dev_init(void) 567{ 568 int res; 569 570 printk(KERN_INFO "i2c /dev entries
driver/n"); 571 572 res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops); 573 if
(res) 574 goto out; 575 576 i2c_dev_class = class_create(THIS_MODULE, "i2c-
dev"); 577 if (IS_ERR(i2c_dev_class)) 578 goto out_unreg_chrdev; 579 580
res = i2c_add_driver(&i2cdev_driver); 581 if (res) 582 goto out_unreg_class; 583
584 return 0; 585 586out_unreg_class: 587 class_destroy(i2c_dev_class);
588out_unreg_chrdev: 589 unregister_chrdev(I2C_MAJOR, "i2c"); 590out: 591
printk(KERN_ERR "%s: Driver Initialisation failed/n", __FILE__); 592 return res; 593}
594 595static void __exit i2c_dev_exit(void) 596{ 597 i2c_del_driver(&i2cdev_driver);
598 class_destroy(i2c_dev_class); 599 unregister_chrdev(I2C_MAJOR,"i2c"); 600} 首
先注册了一个字符型设备驱动,然后注册 i2c_driver,将驱动和 adapter 绑定起来,匹配成
功后将调用 i2c_driver 的 attach_adapter 方法,即 i2cdev_attach_adapter, 建立 dev 设备节点,
并 维 护 了 一 个 i2c_dev 链 表 保 存 设 备 节 点 和 adapter 的 关 系 。
http://lxr.linux.no/#linux+v2.6.25/drivers/i2c/i2c-dev.c#L498 498static int
i2cdev_attach_adapter(struct i2c_adapter *adap) 499{ 500 struct i2c_dev *i2c_dev; 501
int res; 502 503 i2c_dev = get_free_i2c_dev(adap); //添加一个 adapter 到 i2c_dev 列表中
504 if (IS_ERR(i2c_dev)) 505 return PTR_ERR(i2c_dev); 506 507 /* register
this i2c device with the driver core */ 508 i2c_dev->dev = device_create(i2c_dev_class,
&adap->dev, 509 MKDEV(I2C_MAJOR, adap->nr),
510 "i2c-%d", adap->nr); 511 if (IS_ERR(i2c_dev->dev)) {
512 res = PTR_ERR(i2c_dev->dev); 513 goto error; 514 } 515 res =
device_create_file(i2c_dev->dev, &dev_attr_name); 516 if (res) 517 goto
error_destroy; 518 519 pr_debug("i2c-dev: adapter [%s] registered as minor %d/n",