I2C device linux driver

mishaskt picture mishaskt · Jun 1, 2014 · Viewed 9.8k times · Source

How to make a character device for i2c device, with open, close, ioctl etc. functions? I was looking for information about it last two weeks and couldn't find anything working. I found some information in Essential Linux Device Drivers, but it was written for 2.6 kernel, and i use 3.4.79 (i'm trying to write this driver for cubieboard2 on cubian distr) so this book has many deprecated functions, i tried to write my driver like there, but it still don't work (give me kernel errors while i'm truing to cat character device). Can anyone explain me what to do with it, or at least give me a working example.

so, there is my code: http://pastebin.com/T7PBTpym

i just try to get i2c bus works, but on my oscilloscope i don't see anything on i2c lines, while i get no errors when i compile it. Also i can't find how to attach device driver to i2c bus number. because i have 4 i2c buses on my cubieboard2, and how to attach device driver to i2c-1 bus, for example?

Answer

mishaskt picture mishaskt · Jun 1, 2014

Thank you, guys. I've found what I want a couple hours ago. So as I see there are three types of drivers. One is supposed to be inserted into the kernel, and you need to rebuild your kernel to use them. There are also drivers that you can use through the sysfs using device attributes (they appear in /sys/bus/i2c/driver/your_driver/). And, third - my type - drivers that look like character devices. Actually, you can combine them.

So, if you want to use last type of devices it'll be a bit difficult to find correct examples, because almost all examples are devoted to the first two types of drivers. Anyway, if you want to create a character device, you need to describe functions from the file_operations structure. But all functions like i2c_transfer, i2c_smbus_read_byte. Etc. (full list) required eitherstruct i2c_adapter or struct i2c_client. And there two questions, how to get there structures, and how to attach driver to the appropriate i2c bus, such as i2c-2?

So there is a function that is not described here: i2c_get_adapter. As a parameter, you need to pass the i2c bus number. It returns a link to a i2c_adapter structure. The i2c_client structure you can get with i2c_new_dummy function passing i2c_adapter and slave address to it as parameters.

After that you can use functions such as i2c_transfer, i2c_smbus_read_byte etc. In the end you can describe file_operations structure functions, and release driver, representing your i2c device, without using sysfs and rebuilding your kernel.

Result code looks like:

u8 ret; 
struct i2c_client * my_client; 
struct i2c_adapter * my_adap = i2c_get_adapter(1); // 1 means i2c-1 bus
my_client = i2c_new_dummy (my_adap, 0x69); // 0x69 - slave address on i2c bus
i2c_smbus_write_byte(my_client, 0x0f); 
ret = i2c_smbus_read_byte(my_client);

You can use this code directly in your functions for the file_operations structure.

Hope this info will be useful for beginners like me.