1

i have connected a hardware to an embedded linux board on i2c lines. I can see the device at /dev/i2c-1

    filename = "/dev/i2c-1"
    filehandle = open(filename,O_RDWR);
    write(filehandle, <buffer to be written>, <number of Bytes>)

(similiarly for  read =   read(filehandle, <buffer to be read in an array>, <number of Bytes>)

Now my question here is am I using the Linux's i2c-drivers ( read/write) when I am invoking write system calls (and read like above using filehandle).

Also is this implementation independent of i2c module?I verified only after I do modprobe i2c_dev I can see my code running. Is modprobe i2c_dev loading the i2c module and forming the /dev/i2c-1 in the /dev directory since I have connected the i2c device to it.

Raulp
  • 7,758
  • 20
  • 93
  • 155
  • Can you provide [minimal reproducible example](http://sscce.org/)? And also what is the main question here? – Sam Protsenko Feb 23 '16 at 12:03
  • OK , I have updated the Qs with the example ! – Raulp Feb 24 '16 at 04:47
  • thanks for the explanation!!.Can you please elaborate on how the write is associated with the i2c drivers here.(i mean i2c read/write).Where can I look for this association?I am not able to like this read/write with i2c drivers read/write. – Raulp Feb 24 '16 at 11:36
  • I addressed all your questions in new answer. – Sam Protsenko Feb 24 '16 at 17:00

1 Answers1

1

User-space interface to I2C

User-space interface to I2C subsystem is provided via /dev/i2c-* files and documented at Documentation/i2c/dev-interface. There are two ways to send I2C message:

  • send plain buffer via write(); you need to include linux/i2c-dev.h for this
  • send i2c_msg structure via ioctl() with I2C_RDWR request; you need to include linux/i2c.h for this

See this question for examples.

How /dev/i2c-1 is associated with I2C subsystem

/dev/i2c-1 file is just an interface to I2C subsystem. You can send I2C message, receive I2C message and configure I2C using correspondingly write(), read() and ioctl() syscalls. Once you perform one of these operations over /dev/i2c-1 file, it's being passed through Virtual file system to I2C layer, where those operations are implemented. Actual callbacks for those operations are implemented in drivers/i2c/i2c-dev.c file, more specifically -- in i2cdev_fops structure.

For example, when you perform open() syscall on /dev/i2c-1 file, the i2cdev_open() function is called in kernel, which creates i2c_client structure for further send/receive operations, and that structure is being assigned to file's private data field:

/* This creates an anonymous i2c_client, which may later be
 * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
 *
 * This client is ** NEVER REGISTERED ** with the driver model
 * or I2C core code!!  It just holds private copies of addressing
 * information and maybe a PEC flag.
 */
client = kzalloc(sizeof(*client), GFP_KERNEL);
...
file->private_data = client;

When you perform some operations on that /dev/i2c-1 file next, i2c_client structure will be extracted from file->private_data field, and corresponding function will be called for that structure.

For write() syscall the i2cdev_write() function will be called, which leads to i2c_master_send() function call:

struct i2c_client *client = file->private_data;
...
ret = i2c_master_send(client, tmp, count);

The same way read() leads to i2cdev_read(), which leads to i2c_master_recv(). And ioctl() leads to i2cdev_ioctl(), which just assigns corresponding flags to i2c_client structure.

How /dev/i2c-1 is associated with hardware I2C driver

Operations performed on /dev/i2c-* file lead eventually to execution of I2C hardware driver functions. Let's see one example of it. When we are doing write() syscall, the whole chain will be:

write() -> i2cdev_write() -> i2c_master_send() -> i2c_transfer() -> __i2c_transfer() -> adap->algo->master_xfer(), where adap is i2c_adapter structure, which stores hardware specific data about I2C controller, such as callbacks of I2C hardware driver. That .master_xfer callback is implemented in I2C hardware driver. For example, for OMAP platforms it's implemented in drivers/i2c/busses/i2c-omap.c file, see omap_i2c_xfer() function.

Community
  • 1
  • 1
Sam Protsenko
  • 14,045
  • 4
  • 59
  • 75