我想从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
我很感激任何可能出现问题的建议。
我也对如何测试这个问题的想法感兴趣。
答案 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的方式,因此我们需要查阅有关该发行版的文档。