18c2ecf20Sopenharmony_ci============================================ 28c2ecf20Sopenharmony_ciImplementing I2C device drivers in userspace 38c2ecf20Sopenharmony_ci============================================ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ciUsually, I2C devices are controlled by a kernel driver. But it is also 68c2ecf20Sopenharmony_cipossible to access all devices on an adapter from userspace, through 78c2ecf20Sopenharmony_cithe /dev interface. You need to load module i2c-dev for this. 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciEach registered I2C adapter gets a number, counting from 0. You can 108c2ecf20Sopenharmony_ciexamine /sys/class/i2c-dev/ to see what number corresponds to which adapter. 118c2ecf20Sopenharmony_ciAlternatively, you can run "i2cdetect -l" to obtain a formatted list of all 128c2ecf20Sopenharmony_ciI2C adapters present on your system at a given time. i2cdetect is part of 138c2ecf20Sopenharmony_cithe i2c-tools package. 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ciI2C device files are character device files with major device number 89 168c2ecf20Sopenharmony_ciand a minor device number corresponding to the number assigned as 178c2ecf20Sopenharmony_ciexplained above. They should be called "i2c-%d" (i2c-0, i2c-1, ..., 188c2ecf20Sopenharmony_cii2c-10, ...). All 256 minor device numbers are reserved for I2C. 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciC example 228c2ecf20Sopenharmony_ci========= 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciSo let's say you want to access an I2C adapter from a C program. 258c2ecf20Sopenharmony_ciFirst, you need to include these two headers:: 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci #include <linux/i2c-dev.h> 288c2ecf20Sopenharmony_ci #include <i2c/smbus.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciNow, you have to decide which adapter you want to access. You should 318c2ecf20Sopenharmony_ciinspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this. 328c2ecf20Sopenharmony_ciAdapter numbers are assigned somewhat dynamically, so you can not 338c2ecf20Sopenharmony_ciassume much about them. They can even change from one boot to the next. 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciNext thing, open the device file, as follows:: 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci int file; 388c2ecf20Sopenharmony_ci int adapter_nr = 2; /* probably dynamically determined */ 398c2ecf20Sopenharmony_ci char filename[20]; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci snprintf(filename, 19, "/dev/i2c-%d", adapter_nr); 428c2ecf20Sopenharmony_ci file = open(filename, O_RDWR); 438c2ecf20Sopenharmony_ci if (file < 0) { 448c2ecf20Sopenharmony_ci /* ERROR HANDLING; you can check errno to see what went wrong */ 458c2ecf20Sopenharmony_ci exit(1); 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciWhen you have opened the device, you must specify with what device 498c2ecf20Sopenharmony_ciaddress you want to communicate:: 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci int addr = 0x40; /* The I2C address */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci if (ioctl(file, I2C_SLAVE, addr) < 0) { 548c2ecf20Sopenharmony_ci /* ERROR HANDLING; you can check errno to see what went wrong */ 558c2ecf20Sopenharmony_ci exit(1); 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ciWell, you are all set up now. You can now use SMBus commands or plain 598c2ecf20Sopenharmony_ciI2C to communicate with your device. SMBus commands are preferred if 608c2ecf20Sopenharmony_cithe device supports them. Both are illustrated below:: 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci __u8 reg = 0x10; /* Device register to access */ 638c2ecf20Sopenharmony_ci __s32 res; 648c2ecf20Sopenharmony_ci char buf[10]; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* Using SMBus commands */ 678c2ecf20Sopenharmony_ci res = i2c_smbus_read_word_data(file, reg); 688c2ecf20Sopenharmony_ci if (res < 0) { 698c2ecf20Sopenharmony_ci /* ERROR HANDLING: I2C transaction failed */ 708c2ecf20Sopenharmony_ci } else { 718c2ecf20Sopenharmony_ci /* res contains the read word */ 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * Using I2C Write, equivalent of 768c2ecf20Sopenharmony_ci * i2c_smbus_write_word_data(file, reg, 0x6543) 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci buf[0] = reg; 798c2ecf20Sopenharmony_ci buf[1] = 0x43; 808c2ecf20Sopenharmony_ci buf[2] = 0x65; 818c2ecf20Sopenharmony_ci if (write(file, buf, 3) != 3) { 828c2ecf20Sopenharmony_ci /* ERROR HANDLING: I2C transaction failed */ 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */ 868c2ecf20Sopenharmony_ci if (read(file, buf, 1) != 1) { 878c2ecf20Sopenharmony_ci /* ERROR HANDLING: I2C transaction failed */ 888c2ecf20Sopenharmony_ci } else { 898c2ecf20Sopenharmony_ci /* buf[0] contains the read byte */ 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciNote that only a subset of the I2C and SMBus protocols can be achieved by 938c2ecf20Sopenharmony_cithe means of read() and write() calls. In particular, so-called combined 948c2ecf20Sopenharmony_citransactions (mixing read and write messages in the same transaction) 958c2ecf20Sopenharmony_ciaren't supported. For this reason, this interface is almost never used by 968c2ecf20Sopenharmony_ciuser-space programs. 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciIMPORTANT: because of the use of inline functions, you *have* to use 998c2ecf20Sopenharmony_ci'-O' or some variation when you compile your program! 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciFull interface description 1038c2ecf20Sopenharmony_ci========================== 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciThe following IOCTLs are defined: 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci``ioctl(file, I2C_SLAVE, long addr)`` 1088c2ecf20Sopenharmony_ci Change slave address. The address is passed in the 7 lower bits of the 1098c2ecf20Sopenharmony_ci argument (except for 10 bit addresses, passed in the 10 lower bits in this 1108c2ecf20Sopenharmony_ci case). 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci``ioctl(file, I2C_TENBIT, long select)`` 1138c2ecf20Sopenharmony_ci Selects ten bit addresses if select not equals 0, selects normal 7 bit 1148c2ecf20Sopenharmony_ci addresses if select equals 0. Default 0. This request is only valid 1158c2ecf20Sopenharmony_ci if the adapter has I2C_FUNC_10BIT_ADDR. 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci``ioctl(file, I2C_PEC, long select)`` 1188c2ecf20Sopenharmony_ci Selects SMBus PEC (packet error checking) generation and verification 1198c2ecf20Sopenharmony_ci if select not equals 0, disables if select equals 0. Default 0. 1208c2ecf20Sopenharmony_ci Used only for SMBus transactions. This request only has an effect if the 1218c2ecf20Sopenharmony_ci the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just 1228c2ecf20Sopenharmony_ci doesn't have any effect. 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci``ioctl(file, I2C_FUNCS, unsigned long *funcs)`` 1258c2ecf20Sopenharmony_ci Gets the adapter functionality and puts it in ``*funcs``. 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci``ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)`` 1288c2ecf20Sopenharmony_ci Do combined read/write transaction without stop in between. 1298c2ecf20Sopenharmony_ci Only valid if the adapter has I2C_FUNC_I2C. The argument is 1308c2ecf20Sopenharmony_ci a pointer to a:: 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci struct i2c_rdwr_ioctl_data { 1338c2ecf20Sopenharmony_ci struct i2c_msg *msgs; /* ptr to array of simple messages */ 1348c2ecf20Sopenharmony_ci int nmsgs; /* number of messages to exchange */ 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci The msgs[] themselves contain further pointers into data buffers. 1388c2ecf20Sopenharmony_ci The function will write or read data to or from that buffers depending 1398c2ecf20Sopenharmony_ci on whether the I2C_M_RD flag is set in a particular message or not. 1408c2ecf20Sopenharmony_ci The slave address and whether to use ten bit address mode has to be 1418c2ecf20Sopenharmony_ci set in each message, overriding the values set with the above ioctl's. 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci``ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)`` 1448c2ecf20Sopenharmony_ci If possible, use the provided ``i2c_smbus_*`` methods described below instead 1458c2ecf20Sopenharmony_ci of issuing direct ioctls. 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciYou can do plain I2C transactions by using read(2) and write(2) calls. 1488c2ecf20Sopenharmony_ciYou do not need to pass the address byte; instead, set it through 1498c2ecf20Sopenharmony_ciioctl I2C_SLAVE before you try to access the device. 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciYou can do SMBus level transactions (see documentation file smbus-protocol 1528c2ecf20Sopenharmony_cifor details) through the following functions:: 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci __s32 i2c_smbus_write_quick(int file, __u8 value); 1558c2ecf20Sopenharmony_ci __s32 i2c_smbus_read_byte(int file); 1568c2ecf20Sopenharmony_ci __s32 i2c_smbus_write_byte(int file, __u8 value); 1578c2ecf20Sopenharmony_ci __s32 i2c_smbus_read_byte_data(int file, __u8 command); 1588c2ecf20Sopenharmony_ci __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value); 1598c2ecf20Sopenharmony_ci __s32 i2c_smbus_read_word_data(int file, __u8 command); 1608c2ecf20Sopenharmony_ci __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value); 1618c2ecf20Sopenharmony_ci __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value); 1628c2ecf20Sopenharmony_ci __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, 1638c2ecf20Sopenharmony_ci __u8 *values); 1648c2ecf20Sopenharmony_ci __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values); 1658c2ecf20Sopenharmony_ci __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, 1668c2ecf20Sopenharmony_ci __u8 *values); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciAll these transactions return -1 on failure; you can read errno to see 1698c2ecf20Sopenharmony_ciwhat happened. The 'write' transactions return 0 on success; the 1708c2ecf20Sopenharmony_ci'read' transactions return the read value, except for read_block, which 1718c2ecf20Sopenharmony_cireturns the number of values read. The block buffers need not be longer 1728c2ecf20Sopenharmony_cithan 32 bytes. 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciThe above functions are made available by linking against the libi2c library, 1758c2ecf20Sopenharmony_ciwhich is provided by the i2c-tools project. See: 1768c2ecf20Sopenharmony_cihttps://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/. 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ciImplementation details 1808c2ecf20Sopenharmony_ci====================== 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciFor the interested, here's the code flow which happens inside the kernel 1838c2ecf20Sopenharmony_ciwhen you use the /dev interface to I2C: 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci1) Your program opens /dev/i2c-N and calls ioctl() on it, as described in 1868c2ecf20Sopenharmony_ci section "C example" above. 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci2) These open() and ioctl() calls are handled by the i2c-dev kernel 1898c2ecf20Sopenharmony_ci driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(), 1908c2ecf20Sopenharmony_ci respectively. You can think of i2c-dev as a generic I2C chip driver 1918c2ecf20Sopenharmony_ci that can be programmed from user-space. 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci3) Some ioctl() calls are for administrative tasks and are handled by 1948c2ecf20Sopenharmony_ci i2c-dev directly. Examples include I2C_SLAVE (set the address of the 1958c2ecf20Sopenharmony_ci device you want to access) and I2C_PEC (enable or disable SMBus error 1968c2ecf20Sopenharmony_ci checking on future transactions.) 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci4) Other ioctl() calls are converted to in-kernel function calls by 1998c2ecf20Sopenharmony_ci i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter 2008c2ecf20Sopenharmony_ci functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which 2018c2ecf20Sopenharmony_ci performs an SMBus transaction using i2c-core-smbus.c:i2c_smbus_xfer(). 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci The i2c-dev driver is responsible for checking all the parameters that 2048c2ecf20Sopenharmony_ci come from user-space for validity. After this point, there is no 2058c2ecf20Sopenharmony_ci difference between these calls that came from user-space through i2c-dev 2068c2ecf20Sopenharmony_ci and calls that would have been performed by kernel I2C chip drivers 2078c2ecf20Sopenharmony_ci directly. This means that I2C bus drivers don't need to implement 2088c2ecf20Sopenharmony_ci anything special to support access from user-space. 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci5) These i2c.h functions are wrappers to the actual implementation of 2118c2ecf20Sopenharmony_ci your I2C bus driver. Each adapter must declare callback functions 2128c2ecf20Sopenharmony_ci implementing these standard calls. i2c.h:i2c_get_functionality() calls 2138c2ecf20Sopenharmony_ci i2c_adapter.algo->functionality(), while 2148c2ecf20Sopenharmony_ci i2c-core-smbus.c:i2c_smbus_xfer() calls either 2158c2ecf20Sopenharmony_ci adapter.algo->smbus_xfer() if it is implemented, or if not, 2168c2ecf20Sopenharmony_ci i2c-core-smbus.c:i2c_smbus_xfer_emulated() which in turn calls 2178c2ecf20Sopenharmony_ci i2c_adapter.algo->master_xfer(). 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ciAfter your I2C bus driver has processed these requests, execution runs 2208c2ecf20Sopenharmony_ciup the call chain, with almost no processing done, except by i2c-dev to 2218c2ecf20Sopenharmony_cipackage the returned data, if any, in suitable format for the ioctl. 222