从驱动程序代码设置设备权限失败

时间:2017-11-15 09:26:56

标签: linux-device-driver

我想从Linux内核3.10.14中的用户空间访问I2C设备驱动程序节点。 我在内核配置中添加了i2c-dev并获得了/ dev / i2c- *设备节点。但是他们有权限

$ ls -l /dev/i2c-*
crw------- root     root      89,   1 2014-08-21 20:00 i2c-1

在drivers / i2c / i2c-dev.c中我添加了回调

static char *i2c_dev_devnode(struct device *dev, umode_t *mode)
{
    if (!mode)
            return NULL;
    if (MAJOR(dev->devt) == I2C_MAJOR)
            *mode = 0666;
    return NULL;
}

并在同一个文件中我将回调添加到设备类struct:

static int __init i2c_dev_init(void)
{
   ...
   i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
   ...

    /* set access rights */
    i2c_dev_class->devnode = i2c_dev_devnode;
   ...
}

但是设备节点的访问权限仍然是

crw------- root     root      89,   1 2014-08-21 20:00 i2c-1

没有/lib/udev/rules.d或/etc/udev/rules.d

我很感激任何可能出现问题的建议。

我也对如何测试这个问题的想法感兴趣。

3 个答案:

答案 0 :(得分:0)

我理解devnode回调函数的返回值不应该是" NULL"但设备节点名称。 所以, 从" NULL"更改函数返回值到devname。请参阅代码:

----------------------补丁--------------------

diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 6f638bb..35a42c6 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -614,6 +614,14 @@ static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
    .notifier_call = i2cdev_notifier_call,
 };

+static char *i2c_dev_devnode(struct device *dev, umode_t *mode)
+{
+   printk("\n\n****%s: %d\n\n",__func__,__LINE__);
+    if (mode != NULL)
+            *mode = 0666;
+    return kasprintf(GFP_KERNEL, "i2cr/%s", dev_name(dev));;
+}
+
 /* ------------------------------------------------------------------------- */

 /*
@@ -636,7 +644,12 @@ static int __init i2c_dev_init(void)
        goto out_unreg_chrdev;
    }
    i2c_dev_class->dev_groups = i2c_groups;
+   /* set access rights */
+   printk(KERN_INFO "i2c setting devnode\n");
+   i2c_dev_class->devnode = i2c_dev_devnode;
+

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

结果: 不使用此补丁:

root@x86-generic-64:~# ls -l /dev/i2c-*
crw------- 1 root root 89,  0 Nov  1 13:47 /dev/i2c-0
crw------- 1 root root 89,  1 Nov  1 13:47 /dev/i2c-1

有补丁:

root@x86-generic-64:~# ls -l /dev/i2cr/*     
crw-rw-rw- 1 root root 89,  0 Nov  1 13:38 /dev/i2cr/i2c-0
crw-rw-rw- 1 root root 89,  1 Nov  1 13:38 /dev/i2cr/i2c-1

答案 1 :(得分:0)

您可以尝试以下方法。这至少适用于内核4.9.56。

static int my_uevent(struct device *dev, struct kobj_uevent_env *env)
{
    add_uevent_var(env, "DEVMODE=%#o", 0666);
    return 0;
}

static int __init i2c_dev_init(void)
{
   ...
   i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
   ...

   /* set access rights */
   i2c_dev_class->dev_uevent = my_uevent;
   ...
}

答案 2 :(得分:0)

设置设备节点是udev的责任。所以我们需要使用正确的udev规则。如果在引导时间之后加载驱动程序,则进一步的init.rc方法将失败,例如,如果它是可加载模块。您的发行版可能正在使用另一种支持hotplug的方式,因此我们需要查阅有关该发行版的文档。