There are many references to using i2c_smbus_ functions when developing embedded Linux software to communicate on the I2C bus. When i2c_smbus functions such as i2c_smbus_read_word_data are referenced in software project for ARM8 processor errors such as ‘i2c_smbus_read_word_data’ was not declared in this scope are generated at compile.
Investigation of the following header files indicate the absence of most i2c_smbus function definition.
Also in that following reference i2c.h file has all the i2c_smbus defined.
How can this problem be resolved?
Research references
Based on https://unix.stackexchange.com/questions/621854/usr-include-linux-i2c-dev-h-does-not-contain-i2c-smbus-read-word-data-functio, I have found this fixes the function not defined errors:
#include <i2c/smbus.h>
I am currently working with legacy code that references various i2c_smbus functions. It has:
#include <linux/i2c-dev-user.h>
and it fails to compile. Surely, this include used to work, but it seems the lib's header files changed at some point. I did refresh/reinstall libi2c-dev recently.
Note that I added the above include. I can't remove the original include. It is still needed.
FYI: I have not tried cross-compiling yet.
Because you are using a wrong header file for your application.
If you see an extern
on the function i2c_smbus_read_word_data()
in your header, it's a header file for your kernel, but not for your application. The Linux kernel has i2c_smbus_read_word_data()
and other i2c smbus functions for its internal use. But they are a) not system calls, or b) not accessible from your application.
Instead, get i2c-tools from Linux Kernel Wiki and install it. If you are using Debian, just
sudo apt-get install libi2c-dev
and use i2c_smbus_read_word_data()
or any other interfaces they offer.
Version Notes
i2c-dev, untill version 3.x, used be a header only package, meaning that there was no library to link to. All functions were inline functions defined using ioctl()
.
e.g.)
static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
int size, union i2c_smbus_data *data)
{
struct i2c_smbus_ioctl_data args;
args.read_write = read_write;
args.command = command;
args.size = size;
args.data = data;
return ioctl(file,I2C_SMBUS,&args);
}
:
static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
I2C_SMBUS_WORD_DATA,&data))
return -1;
else
return 0x0FFFF & data.word;
}
But since v4.0, it start to be a standard shared library with libi2c.so.0
and i2c/smbus.h
. You have to include the header file in your source code
#include <i2c/smbus.h>
And link libi2c.so.0
with -li2c
gcc -o a.out main.o -li2c
I ran into this today. The i2c_smbus_*
functions are defined in:
/usr/include/linux/i2c-dev.h
...but when I would try to cross-compile for ARM on an older version of Ubuntu, I was running into errors such:
i2c_smbus_read_block_data was not declared in this scope
Turns out the functions are not defined in the equivalent ARM-specific location:
/usr/arm-linux-gnueabi/include/linux/i2c-dev.h
When cross-compiling, this 2nd older header file is the one used. Had to re-declare locally a few of the inline i2c_smbus_... functions to get around the problem.
From the i2c Linux kernel documentation:
Please note that there are two files named "i2c-dev.h" out there, one is distributed with the Linux kernel and is meant to be included from kernel driver code, the other one is distributed with i2c-tools and is meant to be included from user-space programs. You obviously want the second one here.
So you need to include the i2c-dev.h
from i2c-tools not from the Linux kernel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With