Linux Kernel 设备驱动之I2C之i2c设备文件

来源:互联网 发布:sol数据修改器 编辑:程序博客网 时间:2024/03/28 22:04
当提供I2C设备文件时,用户空间可以通过设备文件直接操作设备。这里需要配置
CONFIG_I2C_CHARDEV。

static int __init i2c_dev_init(void){ int res;

 printk(KERN_INFO "i2c /dev entries driver\n");

 res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c"); if (res)  goto out;

 i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); if (IS_ERR(i2c_dev_class)) {  res = PTR_ERR(i2c_dev_class);  goto out_unreg_chrdev; } i2c_dev_class->dev_groups = i2c_groups;

 /* Keep track of adapters which will be added or removed later */ res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); if (res)  goto out_unreg_class;

 /* Bind to already existing adapters right away */ i2c_for_each_dev(NULL, i2cdev_attach_adapter);

 return 0;

out_unreg_class: class_destroy(i2c_dev_class);out_unreg_chrdev: unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);out: printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); return res;}

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 class *i2c_dev_class;

static int i2cdev_attach_adapter(struct device *dev, void *dummy){ struct i2c_adapter *adap; struct i2c_dev *i2c_dev; int res;

 if (dev->type != &i2c_adapter_type)  return 0; adap = to_i2c_adapter(dev);

 i2c_dev = get_free_i2c_dev(adap); if (IS_ERR(i2c_dev))  return PTR_ERR(i2c_dev);

 cdev_init(&i2c_dev->cdev, &i2cdev_fops); i2c_dev->cdev.owner = THIS_MODULE; res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1); if (res)  goto error_cdev;

 /* register this i2c device with the driver core */ i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,         MKDEV(I2C_MAJOR, adap->nr), NULL,         "i2c-%d", adap->nr); if (IS_ERR(i2c_dev->dev)) {  res = PTR_ERR(i2c_dev->dev);  goto error; }

 pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",   adap->name, adap->nr); return 0;error: cdev_del(&i2c_dev->cdev);error_cdev: put_i2c_dev(i2c_dev); return res;}

 
 

static int i2cdev_detach_adapter(struct device *dev, void *dummy){ struct i2c_adapter *adap; struct i2c_dev *i2c_dev;

 if (dev->type != &i2c_adapter_type)  return 0; adap = to_i2c_adapter(dev);

 i2c_dev = i2c_dev_get_by_minor(adap->nr); if (!i2c_dev) /* attach_adapter must have failed */  return 0;

 cdev_del(&i2c_dev->cdev); put_i2c_dev(i2c_dev); device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));

 pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); return 0;}

static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,    void *data){ struct device *dev = data;

 switch (action) { case BUS_NOTIFY_ADD_DEVICE:  return i2cdev_attach_adapter(dev, NULL); case BUS_NOTIFY_DEL_DEVICE:  return i2cdev_detach_adapter(dev, NULL); }

 return 0;}

static struct notifier_block i2cdev_notifier = { .notifier_call = i2cdev_notifier_call,};

 
 
0 0