I've read through the Linux kernel documents on i2c and written a code to try to replicate the command i2cset -y 0 0x60 0x05 0xff
The code that I've written is here:
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <string.h>
int main(){
int file;
file = open("/dev/i2c-0", O_RDWR);
if (file < 0) {
exit(1);
}
int addr = 0x60;
if(ioctl(file, I2C_SLAVE, addr) < 0){
exit(1);
}
__u8 reg = 0x05;
__u8 res;
__u8 data = 0xff;
int written = write(file, ®, 1);
printf("write returned %d\n", written);
written = write(file, &data, 1);
printf("write returned %d\n", written);
}
When I compile and run this code I get:
write returned -1
write returned -1
I've tried to follow exactly what the docs tell me, my understanding is that the address is set first with the call to ioctl
, then I need to write()
the register and then the data that I want sent to the register.
I've also tried to use use SMbus, but I can't get my code to compile using this, it complains at the linking stage that it can't find the functions.
Have I made any mistakes in this code? I'm a beginner to i2c
and don't have a lot of experience with c
either.
EDIT: errno give the following message: Operation not supported
. I am logged in as root on this machine though, so I don't think it can be a permissions thing, although I may be wrong.
The way I got around this problem was to use SMBus, in particular the functions i2c_smbus_write_byte_data
and i2c_smbus_read_byte_data
. I was able to use these functions to successfully read and write to the device.
I did have a little trouble finding these functions, I kept trying to download libraries using apt-get
to install the appropriate header files. In the end I simply downloaded the files smbus.c and smbus.h.
Then the code I needed was:
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "smbus.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
int main(){
int file;
file = open("/dev/i2c-0", O_RDWR);
if (file < 0) {
exit(1);
}
int addr = 0x60;
if(ioctl(file, I2C_SLAVE, addr) < 0){
exit(1);
}
__u8 reg = 0x05; /* Device register to access */
__s32 res;
res = i2c_smbus_write_byte_data(file, reg, 0xff);
close(file);
}
Then if I compile the smbus.c file: gcc -c smbus.c
and myfile: gcc -c myfile.c
, then link them: gcc smbus.o myfile.o -o myexe
I get a working executable that runs my I2C command. Ofcourse, I have smbus.c
and smbus.h
in the same directory as myfile.c
.