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

当提供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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值