linuxubuntui2c

How can I emulate an I2C device on Linux?


I have a custom SOM (based on iMX6) board being developed that will run Ubuntu, and has several I2C devices attached to one of the iMX6 I2C "adapters". Given the hardware is not yet available, I'd like to write software to access and control said I2C devices, preferably by emulating them on my Ubuntu laptop; I'm thinking such as setup might also be useful for software testing.

I've been playing with i2cdetect to see what is on my laptop, and I found a few particularly intriguing things; consider these commands and the responses:

$ sudo i2cdetect -l 
i2c-3   i2c         i915 gmbus dpd                      I2C adapter
i2c-1   i2c         i915 gmbus dpc                      I2C adapter
i2c-6   i2c         DPDDC-C                             I2C adapter
i2c-4   i2c         DPDDC-A                             I2C adapter
i2c-2   i2c         i915 gmbus dpb                      I2C adapter
i2c-0   i2c         Synopsys DesignWare I2C adapter     I2C adapter
i2c-5   i2c         DPDDC-B                             I2C adapter

$ sudo i2cdetect -y -r 4
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
30: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 
50: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 
70: 70 71 72 73 74 75 76 77

I understand this to mean that, for each cell in that table that has a number, a device with that number as its address is present on the bus; for example, the first number, 0x03, means there is a device with I2C address 0x03. It seems rather unlikely that the i2c-4 adapter really has 117 devices attached to it! (FWIW most of the other adapters have no devices, with only two showing a small number of devices on each bus; these appear to be "real" I2C buses.) But back to i2c-4 - is that some sort of simulated (or emulated) adapter with simulated devices on it? I decided to see what I could i2cdump data from one of the suspect devices, and found something like this:

$ sudo i2cdump -y 4 0x3 b
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 02 02 04 04 06 06 08 08 0a 0a 0c 0c 0e 0e    ..??????????????
10: 10 10 12 12 14 14 16 16 18 18 1a 1a 1c 1c 1e 1e    ????????????????
20: 20 20 22 22 24 24 26 26 28 28 2a 2a 2c 2c 2e 2e      ""$$&&((**,,..
30: 30 30 32 32 34 34 36 36 38 38 3a 3a 3c 3c 3e 3e    0022446688::<<>>
40: 40 40 42 42 44 44 46 46 48 48 4a 4a 4c 4c 4e 4e    @@BBDDFFHHJJLLNN
50: 50 50 52 52 54 54 56 56 58 58 5a 5a 5c 5c 5e 5e    PPRRTTVVXXZZ\\^^
60: 60 60 62 62 64 64 66 66 68 68 6a 6a 6c 6c 6e 6e    ``bbddffhhjjllnn
70: 70 70 72 72 74 74 76 76 78 78 7a 7a 7c 7c 7e 7e    pprrttvvxxzz||~~
80: 80 80 82 82 84 84 86 86 88 88 8a 8a 8c 8c 8e 8e    ????????????????
90: 90 90 92 92 94 94 96 96 98 98 9a 9a 9c 9c 9e 9e    ????????????????
a0: a0 a0 a2 a2 a4 a4 a6 a6 a8 a8 aa aa ac ac ae ae    ????????????????
b0: b0 b0 b2 b2 b4 b4 b6 b6 b8 b8 ba ba bc bc be be    ????????????????
c0: c0 c0 c2 c2 c4 c4 c6 c6 c8 c8 ca ca cc cc ce ce    ????????????????
d0: d0 d0 d2 d2 d4 d4 d6 d6 d8 d8 da da dc dc de de    ????????????????
e0: e0 e0 e2 e2 e4 e4 e6 e6 e8 e8 ea ea ec ec ee ee    ????????????????
f0: f0 f0 f2 f2 f4 f4 f6 f6 f8 f8 fa fa fc fc fe fe    ????????????????

This worked for device addresses 0x03 through 0x07; above that, the hex data was replaced with XX! Anyway, I'm guessing this table shows 256 bytes of data on the "device".

I tried to read/write/read a byte, but it doesn't work:

$ sudo i2cget -y 4 0x3 0xff
0xfe

$ sudo i2cset -y 4 0x3 0xff 0x27

$ sudo i2cget -y 4 0x3 0xff
0xfe

With all that as background, here are my questions:

  1. Is i2c-4 really an simulated I2C adapter, and what is its purpose?
  2. Am I using i2cget and i2cset correctly, and if not, where am I going wrong? (Of course, this assumes i2c-4 address 0x3 works as I expected)
  3. If not, is there a way to emulate an I2C device (and probably, adapter) so that I can write software that is able to read/write to it?

Of course, question 3 is the main focus here...

Thanks!


Solution

  • Answering this in case someone else has the same/similar question.

    The secret is to use i2c-stub, which I had heard of but didn't get a clear understanding of what it is. Here is all I was looking for:

    # Install the I2C tools (assumes Debian)
    $ sudo apt install i2c-tools
    # Set up fake device
    $ sudo modprobe i2c-dev
    $ sudo modprobe i2c-stub chip_addr=0x03
    $ i2cdetect -l
    ...
    i2c-7  unknown    SMBus stub driver    N/A    <<--- Here it is!
    
    # Read data
    $ sudo i2cdump -y -r 0-7 7 0x03 b
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 00 00 00 00 00 00 00 00                            .?......        
    
    # Write data
    $ sudo i2cset -y 7 0x03 0x01 0x27
    
    # Read data again
    $ sudo i2cdump -y -r 0-7 7 0x03 b
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 00 27 00 00 00 00 00 00                            .?......