libi2c(3)
π libi2c β bestie edition π
okay so. you know how your kernel has a whole SMBus API and you're sitting there in user space like ποΈπποΈ wishing you had that too? yeah. that's this. welcome to libi2c, the publicly accessible functions provided by the i2c library, straight out of the Linux Programmer's Manual, section 3. it's giving "kernel API but make it user space." periodt.
β¨ SYNOPSIS β¨
no cap, this is the whole roster. first you gotta pull in the headers:
#include <linux/i2c.h>
#include <i2c/smbus.h>
the universal one, the main character of SMBus transactions:
/* Universal SMBus transaction */
__s32 i2c_smbus_access(int file, char read_write, __u8 command,
int size, union i2c_smbus_data *data);
the simple ones, the little guys, the everyday slay:
/* Simple SMBus transactions */
__s32 i2c_smbus_write_quick(int file, __u8 value);
__s32 i2c_smbus_read_byte(int file);
__s32 i2c_smbus_write_byte(int file, __u8 value);
__s32 i2c_smbus_read_byte_data(int file, __u8 command);
__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
__s32 i2c_smbus_read_word_data(int file, __u8 command);
__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
the block ones, chunky queens (and also some non-SMBus ones, we don't gatekeep):
/* Block SMBus (and non-SMBus) transactions */
__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
const __u8 *values);
__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
__u8 *values);
__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
__u8 *values);
__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
const __u8 *values);
πΈ DESCRIPTION πΈ
so what's the vibe here? this library hands user space an SMBus-level API that looks basically identical to the in-kernel one. iconic of it honestly. π«Ά
every single one of these functions is a lil wrapper around the appropriate ioctl call, and that ioctl gets handled by i2c-dev. then the i2c-dev kernel driver converts your ioctl into its in-kernel equivalent function call, and passes the result right back to you, the user-space caller. it's a whole relay race and you're the anchor leg bestie π
π the universal one
i2c_smbus_access() β this is the function. the one that can run any SMBus transaction at all. but here's the catch: you have to fill out and link the data structures yourself. yes, manually. it returns 0 on success, or a negative errno value on error.
lowkey though? in practice you should never need to call this directly. use one of the specific functions below instead β they'll prepare the data and call this for you. let the girlies handle it. π
βοΈ the write transactions
i2c_smbus_write_quick()β runs an SMBus "Quick command" transaction.i2c_smbus_write_byte()β runs an SMBus "Send byte" transaction.i2c_smbus_write_byte_data()β runs an SMBus "Write byte" transaction.i2c_smbus_write_word_data()β runs an SMBus "Write word" transaction.
these write transaction functions return 0 on success. on error, they hand you back a negative errno value. no in between, no vibes-based guessing. π
π the read transactions
i2c_smbus_read_byte()β runs an SMBus "Receive byte" transaction.i2c_smbus_read_byte_data()β runs an SMBus "Read byte" transaction.i2c_smbus_read_word_data()β runs an SMBus "Read word" transaction.i2c_smbus_process_call()β runs an SMBus "Process call" transaction.
these read transaction functions return the read byte or word value on success. on error? yeah you guessed it, negative errno value. π
π§± the block transactions
i2c_smbus_write_block_data()β runs an SMBus "Block write" transaction.i2c_smbus_read_block_data()β runs an SMBus "Block read" transaction.i2c_smbus_block_process_call()β runs an SMBus "Block write-block read process call" transaction.
these block transaction functions return 0 on success. on error, negative errno value. and bestie, listen: the block length is limited to 32 bytes. that's the ceiling. don't fight it. π«
π₯ the I2C block ones (technically not SMBus, still eating)
i2c_smbus_write_i2c_block_data()β runs an "I2C block write" transaction. this is typically used to write to an EEPROM up to 4 kb in size.i2c_smbus_read_i2c_block_data()β runs an "I2C block read" transaction. this is typically used to read from an EEPROM up to 4 kb in size.
and now the tea: while these I2C block transactions are technically not part of the SMBus specification, many SMBus host controllers do support them. so likeβ¦ it's fine. these block transaction functions return 0 on success, and on error a negative errno value. and just like their SMBus counterparts, the block length is limited to 32 bytes. consistency queen π
π DATA STRUCTURES π
okay structure time, grab a snack π
Structure i2c_smbus_ioctl_data is what you use to send data to and retrieve data from the kernel through the i2c-dev driver. and good news: it'll be filled out for you by i2c_smbus_access(), so you do not need to care about the details. slay.
Union i2c_smbus_data is what stores all possible SMBus data. here it is in all its glory:
union i2c_smbus_data {
__u8 byte;
__u16 word;
__u8 block[I2C_SMBUS_BLOCK_MAX + 2];
};
so block[0] is used for length and the last byte is reserved. that's just how it is. β¨
and again for the people in the back: if you use the higher-level functions, this structure will be filled out for you, so you don't have to care about the details. only if you call i2c_smbus_access() directly do you need to fill it out yourself. that's the deal. π€
π BUGS π
got bugs? got fixes? don't be shy, bestie. write to the Linux I2C mailing list <linux-i2c@vger.kernel.org> with a Cc to the current maintainer: Jean Delvare <jdelvare@suse.de>.
π AUTHOR π
Simon G. Vogl, Frodo Looijaard, Jean Delvare and others β legends, all of them. π
that's the whole page, you're welcome. this came from the i2c-tools crew and it's dated September 2020, so if you're reading this in the future just know the girlies were out here documenting SMBus in 2020 and we still appreciate it. mwah. πβ¨π¦
libi2c(3) β periodt. π«Ά
π¦ where this page comes from
- alpine 3.24: i2c-tools-doc 4.4-r3 Β· GPL-2.0-or-later AND LGPL-2.1-or-later
- arch rolling: i2c-tools 4.4-4 Β· GPL
- centos-stream 10: libi2c-devel 4.3-14.el10 Β· LGPL-2.1-or-later
- centos-stream 9: libi2c-devel 4.3-3.el9 Β· LGPLv2+
- centos-stream 9: libi2c-devel 4.3-3.el9 Β· LGPLv2+
- debian bookworm: i2c-tools 4.3-2+b3
- debian trixie: i2c-tools 4.4-2 Β· GPL-2.0-or-later
- fedora 43: libi2c-devel 4.4-3.fc43 Β· LGPL-2.1-or-later
- fedora 43: libi2c-devel 4.4-3.fc43 Β· LGPL-2.1-or-later
- fedora 44: libi2c-devel 4.4-4.fc44 Β· LGPL-2.1-or-later
- fedora 44: libi2c-devel 4.4-4.fc44 Β· LGPL-2.1-or-later
- nixpkgs unstable: i2c-tools 4.4
- opensuse-leap 16.0: i2c-tools 4.4-160000.2.2 Β· GPL-2.0-or-later
- opensuse-leap 16.0: i2c-tools 4.4-160000.2.2 Β· GPL-2.0-or-later
- opensuse-leap 16.0: i2c-tools 4.4-160000.2.2 Β· GPL-2.0-or-later
- opensuse-leap 16.0: i2c-tools 4.4-160000.2.2 Β· GPL-2.0-or-later
- ubuntu jammy: i2c-tools 4.3-2build1
- ubuntu noble: i2c-tools 4.3-4build2
- ubuntu questing: i2c-tools 4.4-2
- ubuntu resolute: i2c-tools 4.4-2build3 Β· GPL-2.0-or-later
- ubuntu stonking: i2c-tools 4.4-3 Β· GPL-2.0-or-later
- Copyright (C) 2019-2020 Jean Delvare <jdelvare@suse.de>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms