I have an i2c adapter exposed to userspace as /dev/i2c-0
. When I use i2cdetect
from the i2c-tools package on that adapter, I see my device listed on this adapter and I am able to perform get, set, and dump operations on it from the command line.
I have some C code that tries to perform a write on it using the ioctl I2C_RDWR
operation.
Here's the stripped-down code that I am working with (provided only for context, and running it isn't important to answering the questions).
fd = open ("/dev/i2c-0", O_RDWR | O_NONBLOCK);
/* other stuff happens here */
if (ioctl (fd, I2C_FUNCS, &funcs) != 0)
return -1;
if (!(funcs & I2C_FUNC_I2C))
return -1;
/* i added this bit of debug just to be sure fd didn't
* get inadvertently closed along the way.
*/
if (fcntl (fd, F_GETFD) != 0) {
return -1;
}
/* build the ioctl message payload */
ret = ioctl (fd, I2C_RDWR, &payload)
if (ret) {
fprintf (stderr, "ioctl returned %d. Reason: %s (errno=%d).",
ret, strerror(errno), errno);
return -1;
}
return 0;
I've also tried using the smbus ioctl functions, which looked like this.
fd = open ("/dev/i2c-0", O_RDWR | O_NONBLOCK);
/* other stuff happens here */
if (ioctl (fd, I2C_FUNCS, &funcs) != 0)
return -1;
if (!(funcs & I2C_FUNC_SMBUS_WORD_DATA))
return -1;
/* i added this bit of debug just to be sure fd didn't
* get inadvertently closed along the way.
*/
if (fcntl (fd, F_GETFD) != 0) {
return -1;
}
/* build the ioctl smbus message payload */
if (ioctl (fd, I2C_SLAVE_FORCE, dev) != 0)
return -1;
ret = ioctl (fd, I2C_SMBUS, &payload);
if (ret) {
fprintf (stderr, "ioctl returned %d. Reason: %s (errno=%d).",
ret, strerror(errno), errno);
return -1;
}
return 0;
In all cases, the program always hits the fprintf
and this is the output:
ioctl returned -1. Reason: No such device or address (errno=6).
According to man 3 ioctl
, the "generic" reason for an ENXIO error is:
ENXIO The request and arg arguments are valid for this device driver, but the service requested cannot be performed on this particular sub-device.
As Ian pointed out in the comments, however, the information regarding STREAMS in the above man page isn't relevant on Linux and I should be using man 2 ioctl
-- which, unfortunately, mostly just says that ioctls don't really conform to any standard, and anything goes.
This raises three questions.
- What does this imply for an i2c adapter? Does the driver for this device not support reading and writing using this method?
- The man page contains specific descriptions of return codes for the I_ prefixed operations, but not for other operations. Is there somewhere else I can look for information specific to I2C ioctl operations?
- Where can I find the source for the i2c ioctl functions?
man 2 ioctl
. – Ian Abbott