2

I’ve developed an NDK application to access an i2c device via the i2c-dev interface. This application is running on an Android development kit, on which we have connected an MPU6050 device via i2c.

I’ve setup the DT binding for the device, as shown below

i2c@78b5000 {                                                           
    MPU6050@68 {
        compatible = "qcom, i2c-msm-v2";
        reg = <0x68>;
    };
};

and enabled the i2c-1 bus – which is the i2c bus the device is connected to – by changing the following line from “disabled” to “okay”

 &i2c_1 {                                                                    
     status = "okay";
 };

The issue is that when I try to open the i2c-1 file in my application via open()

char *filename = "dev/i2c-1";
const int file = open(filename, O_RDWR);

I get the permission denied error code returned.

I have only once successfully read from the WHO-AM-I register, by the following steps:

  1. Adjust the permissions of the /dev/i2c-1 file to 666 using

    $ chmod 666 i2c-1
    
  2. Modify the ueventd.rc file to include this line

    /dev/i2c-1                0666   root       root
    
  3. Kill the ueventd process to allow it to reload.

    $ pgrep ueventd
    $ kill xxx
    

Running ls -la in the /dev folder showed the permissions for i2c-1 as

crw-rw-rw- root root 

More details of this process at this link: Android: how to grant 666 privs to a device via ueventd.rc

The issue with applying this process is that each time the device reboots the ueventd file will be restored back to the original state and the permissions reverted. I have since tried repeating this exact process, rebuilding the boot image with the altered files/permissions and flashing the new boot image to the device. This doesn't seem to work as I still receive the same "permission denied" error.

In an attempt to get around this I included i2ctools into the system image (did not come stock). When trying to run i2cdetect I initially got permission denied, so I followed the same procedure outlined above. This process successfully allowed i2ctools to access /dev/i2c-1 and detect my device.

The problem is that the NDK application - which uses /dev/i2c-1 - is still returning permission denied even after applying the process.

I could potentially modify my application to use i2ctools but my thinking is that if i2ctools can access i2c-1 after modifying the permissions, then my application should be able to - please correct me if i’m wrong.

UPDATE: It seems that I can only use i2ctool if I am running a shell as root; this is with the permissions of i2c-1 set to global read/write. I've also tried setting the permissions of the parent folders in which i2c-1 resides in to 777 - still the same issue.

Can someone please tell me what i'm doing wrong or how I might stop the permission denied error?

Ringo001
  • 163
  • 1
  • 9
  • Use the IIO in-kernel driver -- that will be right thing to do. – 0andriy May 12 '20 at 06:46
  • I looked into IIO and i'm not sure if it's suitable for what I require. I should have noted in my post that I do note have a requirement of fast read/write to/from the i2c device. The MPU6050 is being used as a simple test of the ability to read/write via the i2c bus. In the future we will replace the MPU6050 with an ASIC, which requires setting up by writing a series of configuration bytes to the chip. – Ringo001 May 13 '20 at 00:55
  • IIO is for sensors (MPU6050 has a driver), in general _I2C_ and _fast_ are mutual exclusive. But most performance you can get only by using in-kernel driver or RTOS. – 0andriy May 13 '20 at 07:11
  • I agree with what you are saying, my point is that I need a generic implementation of I2C comms that can send approx 30 bytes at startup. The MPU6050 is only temporary and the device we will be connecting (MIPI-DSI to RGB ASIC) will not have a driver. How hard is it to use IIO if the device we are connecting to doesn't have a driver already written? Most of the resources I've come across seem to talk about IIO and using it with drivers that are already written and available to use. – Ringo001 May 13 '20 at 10:48
  • Okay, IIO makes sense only for your sensor case (MPU6050), for the rest you need in-kernel driver. – 0andriy May 13 '20 at 17:30

1 Answers1

1

It seems that the issue was due to SELinux. Whilst not a permanent solution, I ran the command

$ /system/bin/setenforce 0

from within the adb shell and the application can now gain access to i2c-1 and read successfully from the device.

A more permenent solution would be to create a new SEPolicy rule and set the new policy to be loaded on boot. This post has some more information regarding the topic: https://android.stackexchange.com/questions/207484/how-to-fix-selinux-avc-denied-errors-when-launching-dnscrypt-as-init-d-script/207647#207647

[UPDATE] I've succesffully set SELinux to permissive and it holds after a reboot by editing the BoardConfig.mk file and adding the line

BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive

doing a rebuild of the boot image and flashing the new image to the device.

Ringo001
  • 163
  • 1
  • 9