This guide walks you through the steps of creating a user program that accesses the i2c bus via the /dev/i2c interface. The current version of this guide documents the features used in git commit 8a643e5 and later. If you update this document because of changes to MINIX 3, please mention the commit ID of the change in the wiki comment.
This guide is for “normal” user programs. You should also be aware that you can create a driver service that can interface with the i2c bus driver directly via Minix IPC. That is documented in I2C Driver Programming. In most cases, you will want to create a full driver for the device. However, if you want to make a portable user space program that can access i2c devices and work out of the box on Minix, NetBSD, and OpenBSD, then you can do it using the /dev/i2c interface.
The same /dev/i2c interface that is provided by NetBSD and OpenBSD is available on Minix. That interface is defined here: dev/i2c/i2c_io.h. The general idea is that the program would open() the appropriate i2c device file, prepare a i2c_ioctl_exec_t structure, perform an ioctl(), and finally close() the device.
The device files that user programs need to access are named after the bus they correspond to. For example,
/dev/i2c-1 corresponds to the first i2c bus,
/dev/i2c-2 corresponds to the second i2c bus, etc. This is true even if the hardware manual labels the first i2c bus as i2c0.
There are a few things to consider. Permission to access the i2c bus is controlled by the file permissions on the device file. For example, if
/dev/i2c-3 is owned by root and has a mode of 600, only programs running as root will have access to the bus. It's important to consider who will be using your application and the level of security needed.
In addition, the i2c bus driver has a reservation system that only full drivers, running as services, have access to. The /dev interface only allows access to unclaimed devices. This is to prevent user programs from taking over devices being driven by full drivers. If there is a device driver for a particular device, your program can't access that device through
/dev/i2c-N, instead your program has to contact that driver directly. Also think about the implications of other user programs accessing the device your program is accessing.
There are limits on the maximum amount of data that can be transfered in one step,
I2C_EXEC_MAX_BUFLEN. If you need to transfer more than those limits, you will need to either increase those limits or find a way to split your request into multiple chunks. Note, those constants have different values on Minix and NetBSD. At the time of writing they are 128 on Minix and 32 on NetBSD, but they could change in the future. A well written program will use those constants and not hardcoded lengths.
It would also be important to keep in mind that the bus is shared. On the BeagleBones and BeagleBoard-xM, there are several I2C devices on-board with drivers that periodically access the bus. Your request may be delayed if other programs/drivers are using the bus. This is important to think about with time dependent applications.
There are a couple of examples of using the /dev/i2c interface in the Minix source tree. Those examples are i2cscan and eepromread.