生活随笔
收集整理的这篇文章主要介绍了
New Linux2.6 I2C Driver Model Example
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
闲话不说,先给出完整的示例代码,加好注释,后面再进一步解释。
#include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/list.h> #include <linux/i2c.h> #include <linux/i2c-dev.h> #include <linux/smp_lock.h> #include <linux/jiffies.h> #include <asm/uaccess.h> #include <linux/delay.h> #define I2C_DEV_NAME "MyDevice" //这个名字要跟board_info中的名字一致,才会与I2C_Client匹配 static struct i2c_device_id my_id[] = { {I2C_DEV_NAME,0}, {} }; MODULE_DEVICE_TABLE(i2c, my_id); static struct i2c_client *my_client; static int my_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { my_client = client; return 0; } static int my_i2c_remove(struct i2c_client *client) { //释放I2C Client对象 if( my_client != NULL ) {i2c_unregister_device(my_client);} return 0; } static struct i2c_driver my_driver = { .driver = { .name = "my i2c driver", .owner = THIS_MODULE, }, .probe = my_i2c_probe, .remove = __devexit_p(my_i2c_remove), .id_table = my_id, }; static int __init my_i2c_init(void) { return i2c_add_driver(&my_driver); } static void __exit my_i2c_exit(void) { i2c_del_driver(&my_driver); } int my_i2c_write( uint8_t reg,uint8_t data ) { unsigned char buffer[2]; buffer[0] = reg; buffer[1] = data; if( 2!= i2c_master_send(my_client,buffer,2) ) { printk( KERN_ERR "my i2c send fail! \n" ); return -1; } return 0; } int my_i2c_read( uint8_t reg,uint8_t *data ) { if( 1!= i2c_master_send(my_client,®,1) ) { printk( KERN_ERR "my i2c recv fail! \n" ); return -1; } msleep(10); if( 1!= i2c_master_recv(my_client,data,1) ) { printk( KERN_ERR "my i2c recv fail! \n" ); return -1; } return 0; } MODULE_DESCRIPTION("my i2c driver"); MODULE_AUTHOR("Lujun @HUST"); MODULE_LICENSE("GPL"); module_init(my_i2c_init); module_exit(my_i2c_exit); 上面的代码还不能完全成功运行,因为还没有添加自己的I2C设备信息到系统中,模块Probe函数不会被调用执行。注释中已经提到,i2c_add_driver的时候会扫描本模块的 id_table 中的名称是否与注册到系统中的boardinfo列表中有名称匹配的client,如果有,则会构造 i2c_client 对象,并调用本模块的 probe 函数。
那么,如何注册自己的i2c设备信息到系统的 boardinfo 列表中呢?Linux内核文档:Documentation/i2c/instantiating-devices 中讲了多种方式,我在此只说2种方式。
第一种方式,在内核的初始化中定义你的I2C设备的信息。比如在/arch/arm/mach-xxxx/board_xxxx.c 中添加一个新的 Boardinfo信息:
static struct i2c_board_info __initdata i2c_info[] = { { I2C_BOARD_INFO("24c256", 0x50), .platform_data = &eeprom_info, }, { I2C_BOARD_INFO("MyDevice", (0xbc>>1)), .platform_data = NULL, }, }; 注意,添加的新的 I2C_BOARD_INFO的名称一定要与本模块的driver的名称字符串一致,地址是I2C设备地址右移1位以后的地址。
第二种方式,使用i2c_new_device()。相关函数如下:
struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); struct i2c_adapter* i2c_get_adapter(int id); ls /sys/class/i2c-adapter/ 那么,使用第二种方式的示例代码如下,在 my_i2c_init 函数开头,添加如下代码,动态注册 I2C 设备信息到内核 Boardinfo 列表中。
static struct i2c_board_info my_dev_info[] __initdata = { { I2C_BOARD_INFO(I2C_DEV_NAME,I2C_DEV_ADDR), .platform_data= NULL, }, }; static int sys_adap_bus_num = 0; static int __init my_i2c_init(void) { struct i2c_adapter* adap = i2c_get_adapter(sys_adap_bus_num); if(adap==NULL) { printk("[LUJUN-DEBUG] i2c_get_adapter fail!\n"); return -1; } my_client = i2c_new_device(adap, &my_dev_info[0]); if( my_client==NULL ){ printk("[LUJUN-DEBUG] i2c_new_device fail!\n"); return -1; } i2c_put_adapter(adap); return i2c_add_driver(&my_driver); } 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/971738,如需转载请自行联系原作者
总结
以上是生活随笔为你收集整理的New Linux2.6 I2C Driver Model Example的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。