I am using Raspbian.
First, I'll clarify that the answer is not distro specific; the methodology is exactly the same on any GNU/Linux distro. It is also the same for any model of pi (in fact, it isn't even specific to the pi and would be the same on any linux system with a user I2C bus).
The kernel interface is documented in the official kernel docs. These are included in the source tree in the same path (
Documentation/i2c). Most of the stuff there isn't relevant to using the userland interface in
/dev. The two that are essential are:
"dev_interface": Explains how to open a handle to a specific device according to bus (on the Pi, generally
/dev/i2c-1) and individual address.
"smbus_protocol": Explains various commands that can be used with the device handle. Although, as noted there, the SMBus protocol is actually a subset of I2C, unless you find a specific reason to believe otherwise, assume your device fits into this.
Note that since the device handle is a normal file descriptor, you can use normal
write(), and even
poll() (multiplex!) with it; anecdotely this sometimes seems to produce a different result than an smbus command that ostensibly does the same thing. Anyway, you are free to fool around, nothing is going to get damaged. Probably.
There is no library you need to link to; all the code is in the relevant header,
<linux/i2c-dev.h>. However, there are two versions of this floating around, and they will overwrite one another in
/usr/include. The first one is a useless stub that might be installed with "kernel headers" packages, and you'll get obvious errors regarding undefined functions if you try to use it. The other is much bigger (10k vs 1k), and can be installed on Raspbian with the
libi2c-dev package. This is literally just that header, as (again) there is no pre-compiled userspace library. The core implementation is in the kernel.
The smbus functions defined in that header are mostly wrappers on
ioctl(), so if you can find it on any linux system, regardless of architecture, you can copy it onto a Pi and use it.
This base API is in C, but there are wrappers for it in other languages. Since it isn't actually pi specific, you don't need (or want) to look for stuff that is "for the raspberry pi". You want stuff that is for the linux "dev" based I2C/SMBus interface (although in some cases these were developed on the Pi, the developers themselves are certainly aware of their generic nature1). I have not tried these (I've been using C++), but I did check out their docs, etc., a bit:
- Perl has Dev::SMBus; the best way to install that will be via CPAN.
- Python has smbus; on Raspbian and other Debian derived systems this is in the
- I could not find much for Ruby beyond this thing on github. You may want to use some pi specific GPIO library that includes I2C functions. Note that the smbus library is drop dead simple (have a look at the docs above and the C header), so if you can write Ruby modules which include compiled native code, this would be a pretty easy task.
- Ditto PHP. The github stuff in this case seems to be all "for the raspberry pi"; I didn't look at it.
- For Java, Oracle seems to have a cross-platform deviceaccess.i2cbus class.
The device comes with a lengthy datasheet, but it seems very abstract and I am not sure where to start with corresponding that to code.
This is the hard part, although once you get the hang of it, not necessarily that hard; some devices are more complex than others, obviously. Also, some datasheets are clearer than others. Note that you can ignore very low level stuff about timing of the data line (SDL) in relation to the clock (SCL) since that's taken care of in the driver and reads/writes will be appropriately buffered. All that may or may not be mixed in with references to the data and control register addresses (which might be significant). In general, keep in mind you aren't directly accessing either line. You're using the high level SMBus protocol in userspace, which abstracts away these details.
For example, if the data sheet refers to an (8-bit) read register at
0xF6, you can get the contents with:
int data = i2c_smbus_read_byte_data(device_fd, 0xf6);
For a 16-bit register:
int data = i2c_smbus_read_word_data(device_fs, 0xf6);
But watch out -- some devices are big endian. Some devices also have write only registers that are controlled via a read on the address OR'd with a value.
1. This also means software using them will work on devices such as the Banana Pi, PandaBoard, BeagleBoard, etc. etc.