6

How do you allow non-root users to access I2C on the Raspberry Pi 2?

I've compiled this code for accessing an MPU6050 sensor via I2C, and it works perfectly, but only when I call it via sudo.

I tried adding the pi user to the spi and i2c groups, and adding udev rules as explained here and here, but even after rebooting, those had little effect. I can run /usr/sbin/i2cdetect as a non-root user, but the C code I2Cdev::initialize() still crashes if run without sudo.

This is documented in the underlying bcm2835 library:

If the library runs with any other effective UID (ie not root), then bcm2835_init() will attempt to open /dev/gpiomem, and, if successful, will only permit GPIO operations. In particular, bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all other non-gpio operations may fail silently or crash.

Is there any workaround for this? Even if I add the pi user to the root group, it still silently crashes.

Cerin
  • 2,291
  • 8
  • 33
  • 49

5 Answers5

4

I think the bcm2835 C library is unique in being the only one which drives the I2C peripheral directly rather than using the Linux I2C driver.

This access was needed when the Pi first came out as there was no Linux I2C driver but nowadays it's a bit of an anachronism.

There is nothing stopping you using the standard driver from within the bcm2835 library - it's just standard device calls to /dev/i2c-0 and/or /dev/i2c-1. Using the standard calls might mean you can use bcm2835 without root privileges as long as the user is added to the i2c group.

joan
  • 71,852
  • 5
  • 76
  • 108
2

As Kolban has mentioned, you can use the setuid bit; the example code there is about dropping the privileges at some point, so you do not have to actually add anything to use them, you just need to set the permissions on the compiled executable. You can do this as root or via sudo:

sudo chown root:root MPU6050_example_1
sudo chmod 4755 MPU6050_example_1

Note this won't work with a python or other script, but it will work with a compiled C++ program.

This is a theoretical security risk, although in this context not any more so than running the code sudo.

goldilocks
  • 60,325
  • 17
  • 117
  • 234
2

I believe it only works when using sudo because you are accessing the bcm2835 directly and this requires elevated privileges.

If you use the linux i2c driver (sudo apt-get install i2c-tools will get you everything you need) then you can use device calls (which do not require elevated privileges). The code looks something like this:

    char *deviceName = (char*)"/dev/i2c-1";
    unsigned char bytesToSend[6] = {0,1,2,3,4,5};
    int bytes = 6;
    int i2cAddress = 0x3C;

    if ((i2cHandle = open(deviceName, O_RDWR)) < 0)
    {
        printf("error opening I2C\n");
    }
    else
    {
        if (ioctl(i2cHandle, I2C_SLAVE, i2cAddress) < 0)
        {
            printf("Error at ioctl\n");
        }
        else
        {
            write(i2cHandle, data, bytes);
        }

        // Close the i2c device bus
        close(*deviceName);
    }
KennetRunner
  • 1,050
  • 7
  • 13
1

When I try to ls -l I2C devices, I see the group is i2c.

# ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 1 Mar 18 04:36 /dev/i2c-1

Therefor, I add my user to the group:

# usermod -a -G i2c ubuntu

Then, I exit and login again. And it is works.

By the way I using Ubuntu for Raspberry Pi with Ubuntu Server 20.04.2 LTS image.

bayuah
  • 111
  • 4
-1

The user needs to be in the i2c group and the group members of file /dev/i2c-1 must have read and write permissions. If one of the two conditions is missing. It won t work.

Since we do not know if @Cerin changed the default permissions of the file.

Try changing permissions of the /dev/i2c-1 file. Grant read and write permission to the file owner and the group members (aka root user and members of i2c group.

sudo chmod 660 /dev/i2c-1
UserK
  • 129
  • 5