创建一条虚拟的 I2C 总线定义总线怎么收发数据写i2cset -f -y 3 0x50 0 0x55 ( 往第三条I2C总线的0x50地址写入0x55)读i2cget -f -y 3 0x50 0#include linux/completion.h #include linux/debugfs.h #include linux/delay.h #include linux/gpio/consumer.h #include linux/i2c-algo-bit.h #include linux/i2c.h #include linux/init.h #include linux/interrupt.h #include linux/module.h #include linux/of.h #include linux/platform_data/i2c-gpio.h #include linux/platform_device.h #include linux/slab.h // 先定义一个i2c_adapter的全局变量后面在probe函数中分配和注册这个i2c_adapter static struct i2c_adapter *g_adapter; // 模拟一个eeprom设备地址为0x50容量为512字节 static unsigned char eeprom_buffer[512]; static int eeprom_cur_addr 0; static void eeprom_emulate_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { int i; if (msg-flags I2C_M_RD) { // 读操作从eeprom_buffer中读取数据到msg-buf中 for (i 0; i msg-len; i) { msg-buf[i] eeprom_buffer[eeprom_cur_addr]; if (eeprom_cur_addr 512) eeprom_cur_addr 0; } } else { // 写操作从msg-buf中写数据到eeprom_buffer中 if (msg-len 1) { eeprom_cur_addr msg-buf[0]; for (i 1; i msg-len; i) { eeprom_buffer[eeprom_cur_addr] msg-buf[i]; if (eeprom_cur_addr 512) eeprom_cur_addr 0; } } } } static int i2c_bus_virtual_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { int i; // emulate eeprom , addr 0x50 for (i 0; i num; i) { if (msgs[i].addr 0x50) // 对输入的指令解析若有0x50则进行EEPROM的读写模拟 { eeprom_emulate_xfer(i2c_adap, msgs[i]); } else { i -EIO; break; } } return i; } static u32 i2c_bus_virtual_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_PROTOCOL_MANGLING; } // I2C虚拟总线算法 const struct i2c_algorithm i2c_bus_virtual_algo { .master_xfer i2c_bus_virtual_master_xfer, .functionality i2c_bus_virtual_func, }; // 3. probe函数 static int i2c_bus_virtual_probe(struct platform_device *pdev) { /* get info from device tree, to set i2c_adapter/hardware */ /* alloc, set, register i2c_adapter */ /* 分配设置注册一个 i2c_adapter*/ g_adapter kzalloc(sizeof(*g_adapter), GFP_KERNEL); g_adapter-owner THIS_MODULE; g_adapter-class I2C_CLASS_HWMON | I2C_CLASS_SPD; g_adapter-nr -1; // -1表示让系统自动分配 snprintf(g_adapter-name, sizeof(g_adapter-name), i2c-bus-virtual); g_adapter-algo i2c_bus_virtual_algo; // 编写这个algorithm // 注册这个i2c_adapter到i2c核心注册成功后这个i2c_adapter就可以被用户空间访问 i2c_add_adapter(g_adapter); // i2c_add_numbered_adapter(g_adapter); return 0; } // remove函数 static int i2c_bus_virtual_remove(struct platform_device *pdev) { // 清除 adapter i2c_del_adapter(g_adapter); return 0; } // 和设备树中的 compatible 匹配即compatible 100ask,i2c-bus-virtual一旦匹配成功就调用platform_driver中的probe函数 static const struct of_device_id i2c_bus_virtual_dt_ids[] { { .compatible 100ask,i2c-bus-virtual, }, { /* sentinel */ } }; // 2. platform_driver结构体 static struct platform_driver i2c_bus_virtual_driver { .driver { .name i2c-gpio, .of_match_table of_match_ptr(i2c_bus_virtual_dt_ids), }, .probe i2c_bus_virtual_probe, .remove i2c_bus_virtual_remove, }; // 入口函数-和出口函数对应 static int __init i2c_bus_virtual_init(void) { int ret; ret platform_driver_register(i2c_bus_virtual_driver); // 注册一个platform_driver if (ret) printk(KERN_ERR i2c-gpio: probe failed: %d\n, ret); return ret; } module_init(i2c_bus_virtual_init); // 出口函数 static void __exit i2c_bus_virtual_exit(void) { platform_driver_unregister(i2c_bus_virtual_driver); } module_exit(i2c_bus_virtual_exit); MODULE_AUTHOR(www.100ask.net); MODULE_LICENSE(GPL);