I2C Data Transfer With i2c_transfer
Free Linux Kernel Development Course — I2C Client Drivers, Part 3
free linux device drivers course
i2c_transfer i2c_msg linux kernel
free linux kernel development course
i2c_master_send i2c_master_recv
So far in this free linux device drivers course we’ve built an I2C client driver that probes, registers, and cleans up correctly — but it has never actually talked to the device on the bus. This lecture fixes that. We’ll cover the two core I2C communication APIs, i2c_master_send()/i2c_master_recv() and the more flexible i2c_transfer(), and use i2c_transfer i2c_msg linux kernel techniques to build a real register-read operation, the single most common thing an I2C driver ever does.
What You Will Learn
- The difference between plain I2C communication and SMBus-compatible communication
- How i2c_master_send() and i2c_master_recv() work for simple byte transfers
- The structure and meaning of every field in struct i2c_msg
- How i2c_transfer() lets you combine a write and a read into one atomic bus transaction
- How to write an original two-message register-read function for a sensor-style device
Prerequisites
This lecture builds directly on the previous one, where we covered probe(), remove(), and driver registration. You should already have a working ep_gpio_demo-style skeleton driver, and be comfortable retrieving your private data with i2c_get_clientdata(). No new hardware is required beyond what you used previously — any I2C device that exposes readable registers will work for testing.
Two Ways to Talk I2C: Plain vs SMBus
The I2C core actually offers two overlapping sets of communication functions. The “plain” I2C API works with any I2C device and gives you full control over the exact bytes on the wire. A second API, the SMBus-compatible functions, offers convenience calls like “read one byte from this register” — these work on true SMBus devices and on the majority of I2C devices too, but not the other way around: a plain I2C-only device may not support every SMBus convenience call. This lecture focuses on the plain I2C API, since it’s the one that works everywhere and teaches you what’s actually happening on the wire; we’ll cover the SMBus convenience functions in a later lecture.
Simple Transfers: i2c_master_send and i2c_master_recv
For the simplest case — just writing a block of bytes, or just reading a block of bytes, with no combined write-then-read in a single bus transaction — the I2C core gives you two straightforward functions:
int i2c_master_send(struct i2c_client *client, const char *buf, int count);
int i2c_master_recv(struct i2c_client *client, char *buf, int count);
Both take the client handle, a buffer, and a byte count, and both return the number of bytes actually transferred (or a negative errno on failure). These are genuinely simple — perfect for devices where writing a command byte or reading a status byte is the entire operation, with no register addressing scheme involved.
u8 status;
int ret;
ret = i2c_master_recv(client, &status, 1);
if (ret != 1) {
dev_err(&client->dev, "status read failed: %d\n", ret);
return ret < 0 ? ret : -EIO;
}
Why You Usually Need Something More: struct i2c_msg
Most real I2C devices — sensors, EEPROMs, expanders — don’t work like that. They expose multiple internal registers, and reading one means first writing the register address, then reading the value back, without releasing the bus in between. i2c_master_send() and i2c_master_recv() can’t do that in one atomic operation because each call is a separate, independent bus transaction. For this, the I2C core gives you lower-level message-based control:
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num);
i2c_transfer() sends an array of messages as one combined operation — each message can independently be a read or a write, and crucially, there is no I2C STOP condition between the messages in the array, only a repeated START. That’s exactly the “write register address, then read value” pattern that real devices need.
| START | Slave Address + Write | Register Address Byte(s) | Repeated START | Slave Address + Read | Data Byte(s) | STOP |
struct i2c_msg Field by Field
Every element of the array you pass to i2c_transfer() is one struct i2c_msg. Here’s what each field means:
| Field | Type | Meaning |
|---|---|---|
| addr | __u16 | 7-bit (or 10-bit) slave address of the target device |
| flags | __u16 | 0 for a write, I2C_M_RD for a read; other flags exist for 10-bit addressing etc. |
| len | __u16 | Number of bytes in this message — note the 16-bit width, so a single message can never exceed 65535 bytes |
| buf | __u8 * | Pointer to the data — bytes to write, or the buffer to fill on a read |
Note: because len is a 16-bit field, you must always keep your read and write buffer sizes below 65536 bytes per message. For anything larger, you split the transfer into multiple i2c_transfer() calls at the driver level.
Original Example: ep_temp_read_reg
Here is an original register-read helper, written for this course, for a hypothetical temperature sensor with 8-bit register addressing and 16-bit register values:
#define EP_TEMP_REG_DATA 0x03
static int ep_temp_read_reg(struct i2c_client *client, u8 reg, u16 *value)
{
u8 wbuf[1] = { reg };
u8 rbuf[2];
struct i2c_msg msg[2];
int ret;
msg[0].addr = client->addr;
msg[0].flags = 0; /* write */
msg[0].len = 1;
msg[0].buf = wbuf;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD; /* read */
msg[1].len = 2;
msg[1].buf = rbuf;
ret = i2c_transfer(client->adapter, msg, 2);
if (ret != 2)
return ret < 0 ? ret : -EIO;
*value = (rbuf[0] << 8) | rbuf[1];
return 0;
}
Walking through this: the first message writes a single byte, the register address we want to read. The second message reads two bytes back, with I2C_M_RD set so the I2C core knows to issue a read instead of a write. Both messages target the same client->addr, and i2c_transfer() handles the repeated-START sequencing between them automatically — your driver never touches START/STOP conditions directly.
Wiring It Into probe()
Using this helper from our driver skeleton looks like:
static int ep_temp_probe(struct i2c_client *client)
{
u16 raw;
int ret;
ret = ep_temp_read_reg(client, EP_TEMP_REG_DATA, &raw);
if (ret) {
dev_err(&client->dev, "failed to read temp register: %d\n", ret);
return ret;
}
dev_info(&client->dev, "ep_temp: raw register value = 0x%04x\n", raw);
return 0;
}
Expected dmesg output on a successful load with a real device present:
[ 201.884511] ep_temp 1-0048: ep_temp: raw register value = 0x0173
If the device is missing or not acknowledging, you’ll instead see the driver’s own error print, typically with -ENXIO or -ETIMEDOUT as the returned error code, rather than a silent hang — i2c_transfer() always returns a definite success or error result.
Common Mistakes and Troubleshooting
| Mistake | Symptom | Fix |
|---|---|---|
| Forgetting I2C_M_RD on the read message | Both messages sent as writes; device NACKs or returns garbage | Set msg[1].flags = I2C_M_RD; explicitly |
| Checking ret != 0 instead of ret != num | Partial transfers silently treated as success | i2c_transfer() returns the number of messages completed — compare against the array length |
| Using a stack buffer that goes out of scope during a deferred/async transfer | Corrupted reads, intermittent failures | Keep buffers valid for the full duration of the call; i2c_transfer() is synchronous, but async wrappers built on top of it need heap or persistent buffers |
| Assuming len can exceed 65535 | Silent truncation or compiler warning on overflow | Split large transfers into multiple i2c_transfer() calls |
Best Practices
- Always check i2c_transfer()’s return value against the exact number of messages you sent, not just “non-negative”.
- Keep write buffers (like the register address byte) as local const arrays — don’t reuse a buffer across messages that need different content.
- Prefer i2c_transfer() over two separate i2c_master_send()/i2c_master_recv() calls whenever a device needs the register address preserved across the write-to-read boundary.
- Log the specific errno on failure (dev_err with %d) rather than a generic “read failed” message — it saves significant debugging time on real hardware.
Performance Considerations
Because i2c_transfer() combines multiple messages into a single bus transaction, it is almost always faster and more reliable than issuing separate send/recv calls, since it avoids releasing and re-arbitrating the bus between the write and the read. On a shared I2C bus with multiple devices, this also reduces the chance that another master or transaction interrupts your register read halfway through.
Summary and Key Takeaways
- i2c_master_send()/i2c_master_recv() are for simple, standalone byte transfers.
- i2c_transfer() combines multiple i2c_msg entries into one atomic bus operation using a repeated START.
- struct i2c_msg’s len field is 16-bit, capping any single message at 65535 bytes.
- The write-then-read pattern (register address, then data) is the standard way to read registers on I2C devices, and it requires i2c_transfer(), not two separate calls.
Conclusion
You now have everything needed to make a real I2C client driver both register itself correctly and communicate with actual hardware — from probe() and remove() through to a working register read using i2c_transfer(). This combination covers the vast majority of what real-world I2C client drivers in the mainline kernel actually do. As you continue through this free linux kernel development course, the next lecture will look at the SMBus-compatible convenience API as an alternative to raw i2c_transfer() calls.
Frequently Asked Questions
What’s the difference between i2c_master_send/recv and i2c_transfer?
i2c_master_send/recv each perform one independent bus transaction. i2c_transfer sends an array of messages as a single combined transaction with no STOP condition between them, which is required for register-address-then-read patterns.
What does I2C_M_RD do?
It marks a struct i2c_msg as a read operation. Without it, the message defaults to a write.
How many bytes can one i2c_msg transfer?
Up to 65535, since the len field is a 16-bit unsigned integer.
Does i2c_transfer block the calling context?
Yes, it is a synchronous call that returns once the transaction completes or fails — it should not be called from atomic/interrupt context.
How do I know if my transfer partially failed?
Compare the return value of i2c_transfer() against the number of messages you passed in; a smaller number means only that many messages completed.
Should I use SMBus functions instead of i2c_transfer?
SMBus convenience functions are simpler for basic register reads but not supported by every I2C-only device. i2c_transfer works universally and gives full control, which is why we teach it first.
Continue Your Free Linux Device Drivers Course
Next: SMBus-compatible convenience functions for I2C devices.
