【IMX6ULL驱动开发学习】09.Linux之I2C驱动框架简介和驱动程序模板( 四 )


函数用于向 I2C 设备多个寄存器写数据 。数组 b 用于存放寄存器首地址和要发送的数据,msg 的 addr设置为 I2C 器件地址 。然后设置 msg 的 flags 为 0,也就是写数据 。设置要发送的数据,也就是数组 b 。设置 msg 的 len 为 len+1,因为要加上一个字节的寄存器地址 。最后通过函数完成向 I2C 设备的写操作 。
另外还有两个API函数分别用于I2C数据的收发操作,这两个函数都会调用 。
I2C 数据发送函数 :
int i2c_master_send(const struct i2c_client *client,const char *buf,int count)
: I2C 设备对应的
buf:要发送的数据
count: 要发送的数据字节数,要小于 64KB,以为的 len 成员变量是一个 u16(无
符号 16 位)类型的数据 。
返回值: 负值,失败,其他非负值,发送的字节数
I2C 数据接收函数为 :
int i2c_master_recv(const struct i2c_client *client,char *buf,int count)
: I2C 设备对应的
buf:要接收的数据
count: 要接收的数据字节数,要小于 64KB,以为的 len 成员变量是一个 u16(无
符号 16 位)类型的数据
返回值: 负值,失败,其他非负值,发送的字节数
三、Linux I2C驱动程序模板
.c
【【IMX6ULL驱动开发学习】09.Linux之I2C驱动框架简介和驱动程序模板】#include "linux/i2c.h"#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 主设备号*/static int major = 0;static struct class *my_i2c_class;struct i2c_client *g_client;static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);struct fasync_struct *i2c_fasync;/* 实现对应的open/read/write等函数,填入file_operations结构体*/static ssize_t i2c_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset){int err;struct i2c_msg msgs[2];/* 初始化i2c_msg */err = i2c_transfer(g_client->adapter, msgs, 2);/* copy_to_user*/return 0;}static ssize_t i2c_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset){int err;/* copy_from_user*/struct i2c_msg msgs[2];/* 初始化i2c_msg */err = i2c_transfer(g_client->adapter, msgs, 2);return 0;}static unsigned int i2c_drv_poll(struct file *fp, poll_table * wait){//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);poll_wait(fp, &gpio_wait, wait);//return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;return 0;}static int i2c_drv_fasync(int fd, struct file *file, int on){if (fasync_helper(fd, file, on, &i2c_fasync) >= 0)return 0;elsereturn -EIO;}/* 定义自己的file_operations结构体*/static struct file_operations i2c_drv_fops = {.owner= THIS_MODULE,.read= i2c_drv_read,.write= i2c_drv_write,.poll= i2c_drv_poll,.fasync= i2c_drv_fasync,};static int i2c_drv_probe(struct i2c_client *client,const struct i2c_device_id *id){// struct device_node *np = client->dev.of_node;从client获取设备节点// struct i2c_adapter *adapter = client->adapter;从client获取控制器/* 记录client */g_client = client;/* 注册字符设备 *//* 注册file_operations*/major = register_chrdev(0, "100ask_i2c", &i2c_drv_fops);/* /dev/gpio_desc */my_i2c_class = class_create(THIS_MODULE, "100ask_i2c_class");if (IS_ERR(my_i2c_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "100ask_i2c");return PTR_ERR(my_i2c_class);}device_create(my_i2c_class, NULL, MKDEV(major, 0), NULL, "myi2c"); /* /dev/myi2c */return 0;}static int i2c_drv_remove(struct i2c_client *client){/* 反注册字符设备 */device_destroy(my_i2c_class, MKDEV(major, 0));class_destroy(my_i2c_class);unregister_chrdev(major, "100ask_i2c");return 0;}static const struct of_device_id myi2c_dt_match[] = {{ .compatible = "100ask,i2cdev" },{},};static struct i2c_driver my_i2c_driver = {.driver = {.name = "100ask_i2c_drv",.owner = THIS_MODULE,.of_match_table = myi2c_dt_match,},.probe = i2c_drv_probe,.remove = i2c_drv_remove,};static int __init i2c_drv_init(void){/* 注册i2c_driver */return i2c_add_driver(&my_i2c_driver);}static void __exit i2c_drv_exit(void){/* 反注册i2c_driver */i2c_del_driver(&my_i2c_driver);}/* 7. 其他完善:提供设备信息,自动创建设备节点*/module_init(i2c_drv_init);module_exit(i2c_drv_exit);MODULE_LICENSE("GPL");