1. Linux kernel support I²C Universal device driver (user-driven: the implementation of hardware control by the application layer can be called the user-state driver), the implementation file is located in Drivers/i2c/i2c-dev.c, the device file is/dev/i2c-0
2. I²C Universal device driver registered in the kernel with a character device
Static Const struct file_operations i2cdev_fops = { . owner = this_module, . Llseek = No_llseek,. read = i2cdev_read,. write = i2cdev_write, . Unlocked_ioctl = i2cdev_ioctl, . Open = i2cdev_open, . Release ="i²c", &i2cdev_fops);
3. Read, write, or IOCTL methods can be called when reading or writing the device files, and they are all implemented by calling the function I2c_transfer .
intI2c_transfer (structI2c_adapter * ADAP,structI2c_msg *msgs,intnum) { intret; /*revisit the fault reporting model here's weak: * *-When we get an error after receiving N bytes from a SL Ave, * There is no-to-report "N". * *-When we get a NAK after transmitting n bytes to a slave, * there is no ' to ' n ' ... or to let T He master * Continue executing the rest of this combined a message, if * that ' s the appropriate response. * *-When for example ' num ' is a and we successfully complete * The first message but get a error part WA Y through the * second, it's unclear whether that should being reported as * one (discarding status on the Seco ND message) or errno * (discarding status on the first one). */ if(adap->algo->Master_xfer) {#ifdef DEBUG for(ret =0; RET < num; ret++) {dev_dbg (&adap->dev,"master_xfer[%d]%c, addr=0x%02x," "len=%d%s\n", ret, (Msgs[ret].flags &i2c_m_rd)?'R':'W', Msgs[ret].addr, Msgs[ret].len, (Msgs[ret].flags& I2c_m_recv_len)?"+":""); }#endif if(In_atomic () | |irqs_disabled ()) {ret= Mutex_trylock (&adap->Bus_lock); if(!ret)/*i²c activity is ongoing.*/ return-Eagain; } Else{mutex_lock_nested (&adap->bus_lock, adap->Level ); } ret= adap->algo->Master_xfer (Adap,msgs,num); Mutex_unlock (&adap->Bus_lock); returnret; } Else{dev_dbg (&adap->dev,"i²c level transfers not supported\n"); return-Eopnotsupp; }}
4. I2c_transfer through the code can be seen, i2c_transfer by invoking the corresponding adapter Master_xfer method, and Master_xfer is mainly based on the struct I2C_MSG Type of msgs to be processed.
structi2c_msg {__u16 addr; /*slave Address*/__U16 flags;#defineI2c_m_ten 0x0010/* This is a TEN bit chip address */#defineI2C_M_RD 0x0001/* read data, from slave to master */#defineI2c_m_nostart 0x4000/* If i2c_func_protocol_mangling */#defineI2C_M_REV_DIR_ADDR 0x2000/* If i2c_func_protocol_mangling */#defineI2c_m_ignore_nak 0x1000/* If i2c_func_protocol_mangling */#defineI2c_m_no_rd_ack 0x0800/* If i2c_func_protocol_mangling */#defineI2c_m_recv_len 0x0400/* Length'll be first received BYTE */__u16 Len; /*msg Length*/__u8*buf;/*pointer to msg data*/};
5. User-Driven Simple example
Linux I²c Drive-user-driven simple example