The i2c-stub module is a fake I2C/SMBus driver. This post demonstrates how to use this module to emulate a device.
Pre-requisites
- a copy of the kernel source
- have i2c-tools installed1; we’re going to utilize i2cset from there.
- specify a target chip driver, in this demo we’ll use drivers/iio/light/al3320a
- any documentation2 about the target chip driver, this could be the source code, a datasheet or any other material where you can find the addresses needed by i2c-stub and i2cset.
- knowledge about configuring and installing a kernel from source
Setting it up
Compile and install your copy of the kernel source. Make sure to configure the i2c-stub and the target chip driver as a module.
make menuconfig
Device Drivers -> I2C support -> I2C/SMBus Test Stub
Next, we need to find the addresses required by the i2c-stub module and i2cset. The i2c-stub needs the I2C slave address. On our target driver, it can be found on the header of the source code which is 0x1C. For i2cset, we need the addresses of registers supported by the driver for read and write. We’ll be using these addresses (also taken from the source code):
#define AL3320A_REG_CONFIG_RANGE 0x07
This is where the scale can be read or written from. I’ll explain the meaning of scale in a future post.
#define AL3320A_REG_DATA_LOW 0x22
Data from the device can be read from here. This register in particular corresponds to the low byte of the device’s output.
Usage
From the i2c-stub documentation, usage is as follows:
load the i2c-stub module.
$ modprobe i2c-stub chip_addr=0x1c
Use the slave address noted in the previous section to specify the chip_addr module parameter required in loading i2c-stub
use i2cset to pre-load some data on the addresses found earlier.
$ i2cset 4 0x1C 0x07 0x04 b
$ i2cset 4 0x1C 0x22 0x64 w
i2cset is used to set the I2C registers. The first parameter passed refers to the number of the I2C bus associated with i2c-stub. This number can be noted by executing the i2cdetect -l command. The second parameter is the slave address while the third parameter correspond to the register address noted previously.
The last two parameters refer to the value to write and the write size. The man page explains all these in detail if you want to know more.
load the target chip driver module.
This is accomplished by executing the following command:
$ echo al3320a 0x1c > /sys/class/i2c-adapter/i2c-4/new_device
The name of the target driver and its slave address were used to instantiate3 the device.
observe its behavior in the kernel log.
You may use dmesg for this.
See it in Action
Here’s a full terminal session for demonstration:
Wrapping Up
The sysfs attributes associated with al3320a can now be seen after instantiating the device. It’s as if you had plugged the actual hardware in there! Amazing, isn’t it? This leads to an interesting use-case for i2c-stub which is for testing the code without the actual device.
In the previous section, I tried reading and writing on the exposed attributes and they work as expected. The value I specified for the data4 register reads correctly and the scale can be written and read without issue.
That’s it! Thanks for reading!
-
Can be obtained via the lm-sensors site or through this cloned repository. ↩
-
We need to know the chip address of the target as well as register addresses you need to read/write from. ↩
-
0x64 - a hex value is 100 in decimal notation. ↩