1

I want to access I2C device driver nodes from user space in a linux kernel 3.10.14. I added i2c-dev in the kernel configuration and got the /dev/i2c-* device nodes. However they have permission

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

In drivers/i2c/i2c-dev.c I added the callback

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;
}

and in the same file I added the callback to the device class 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;
   ...
}

However the access rights of the device node remain

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

There is no /lib/udev/rules.d or /etc/udev/rules.d

I would appreciate any suggestions what might go wrong here.

I am also interested in ideas how to test this issue.

3 Answers3

2

You might try the following. This works at least with kernel 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;
   ...
}
Mr. T
  • 81
  • 4
1

I understand the return value of devnode callback function shall not be "NULL" but device node name. So, Change your functions return value from "NULL" to devname. Refer the code:

----------------------patch--------------------

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)

Results: Without applying this patch:

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

With patch:

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

rk1825
  • 273
  • 4
  • 14
  • 1
    This did not change the permissions of the device file. – keepitintheground Nov 22 '17 at 08:16
  • In drivers/i2c/i2c-dev.c I also found the helper macro DEVICE_ATTR for defining device attributes: It is used as: static DEVICE_ATTR(foo, S_IRUGO, show_foo, store_foo); so permissions of /dev/i2c-* should be cr--r--r-- but are not. – keepitintheground Nov 22 '17 at 08:48
  • I tested this for you. This work perfectly. Putting below patch & test res. – rk1825 Nov 22 '17 at 12:15
  • I am not able to add longer text here.. so Edited answer with working patch & results. Hope this helps. – rk1825 Nov 22 '17 at 12:27
  • Thanks for all your help. But the return value (i2cr/%s) seems to be ignored in my setting, since there is no directory /dev/i2cr created (or did you create it manually?) I set permissions now by chmod 0666 /dev/i2c-* in init.rc – keepitintheground Nov 25 '17 at 10:50
0

Setting up device node is responsibility of udev. So we need to use correct udev rule. Further init.rc approach will fail if driver is loaded after boot time for example in case it is a loadable module. Your distribution might be using another way of supporting hotplug so we need to consult documentation about that distro.

Hercules dd
  • 215
  • 1
  • 5