驱动13.i2c设备驱动程序
1 分析i2c设备的识别过程
i2c_add_driver
i2c_register_driver
driver->driver.bus = &i2c_bus_type;
driver_register(&driver->driver);
list_for_each_entry(adapter, &adapters, list) {
driver->attach_adapter(adapter);
i2c_probe(adapter, &addr_data, eeprom_detect);
i2c_probe_address // 发出S信号,发出设备地址(来自addr_data)
i2c_smbus_xfer
i2c_smbus_xfer_emulated
i2c_transfer
adap->algo->master_xfer // s3c24xx_i2c_xfer
2 怎么写I2C设备驱动程序?
2.1 分配一个i2c_driver结构体
2.2 设置
attach_adapter // 它直接调用 i2c_probe(adap, 设备地址, 发现这个设备后要调用的函数);
detach_client // 卸载这个驱动后,如果之前发现能够支持的设备,则调用它来清理
2.3 注册:i2c_add_driver
3 写代码
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <asm/uaccess.h> static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; /* 地址值是7位 */
/* 改为0x60的话, 由于不存在设备地址为0x60的设备, 所以at24cxx_detect不被调用 */ static unsigned short force_addr[] = {ANY_I2C_BUS, 0x60, I2C_CLIENT_END};
static unsigned short * forces[] = {force_addr, NULL}; static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr, /* 要发出S信号和设备地址并得到ACK信号,才能确定存在这个设备 */
.probe = ignore,
.ignore = ignore,
//.forces = forces, /* 强制认为存在这个设备 */
}; static struct i2c_driver at24cxx_driver; static int major;
static struct class *cls;
struct i2c_client *at24cxx_client; static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
{
unsigned char address;
unsigned char data;
struct i2c_msg msg[];
int ret; /* address = buf[0]
* data = buf[1]
*/
if (size != )
return -EINVAL; copy_from_user(&address, buf, ); /* 数据传输三要素: 源,目的,长度 */ /* 读AT24CXX时,要先把要读的存储空间的地址发给它 */
msg[].addr = at24cxx_client->addr; /* 目的 */
msg[].buf = &address; /* 源 */
msg[].len = ; /* 地址=1 byte */
msg[].flags = ; /* 表示写 */ /* 然后启动读操作 */
msg[].addr = at24cxx_client->addr; /* 源 */
msg[].buf = &data; /* 目的 */
msg[].len = ; /* 数据=1 byte */
msg[].flags = I2C_M_RD; /* 表示读 */ ret = i2c_transfer(at24cxx_client->adapter, msg, );
if (ret == )
{
copy_to_user(buf, &data, );
return ;
}
else
return -EIO;
} static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
unsigned char val[];
struct i2c_msg msg[];
int ret; /* address = buf[0]
* data = buf[1]
*/
if (size != )
return -EINVAL; copy_from_user(val, buf, ); /* 数据传输三要素: 源,目的,长度 */
msg[].addr = at24cxx_client->addr; /* 目的 */
msg[].buf = val; /* 源 */
msg[].len = ; /* 地址+数据=2 byte */
msg[].flags = ; /* 表示写 */ ret = i2c_transfer(at24cxx_client->adapter, msg, );
if (ret == )
return ;
else
return -EIO;
} static struct file_operations at24cxx_fops = {
.owner = THIS_MODULE,
.read = at24cxx_read,
.write = at24cxx_write,
}; static int at24cxx_detect(struct i2c_adapter *adapter, int address, int kind)
{
printk("at24cxx_detect\n"); /* 构构一个i2c_client结构体: 以后收改数据时会用到它 */
at24cxx_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
at24cxx_client->addr = address;
at24cxx_client->adapter = adapter;
at24cxx_client->driver = &at24cxx_driver;
strcpy(at24cxx_client->name, "at24cxx");
i2c_attach_client(at24cxx_client); major = register_chrdev(, "at24cxx", &at24cxx_fops); cls = class_create(THIS_MODULE, "at24cxx");
class_device_create(cls, NULL, MKDEV(major, ), NULL, "at24cxx"); /* /dev/at24cxx */ return ;
} static int at24cxx_attach(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, at24cxx_detect);
} static int at24cxx_detach(struct i2c_client *client)
{
printk("at24cxx_detach\n");
class_device_destroy(cls, MKDEV(major, ));
class_destroy(cls);
unregister_chrdev(major, "at24cxx"); i2c_detach_client(client);
kfree(i2c_get_clientdata(client)); return ;
} /* 1. 分配一个i2c_driver结构体 */
/* 2. 设置i2c_driver结构体 */
static struct i2c_driver at24cxx_driver = {
.driver = {
.name = "at24cxx",
},
.attach_adapter = at24cxx_attach,
.detach_client = at24cxx_detach,
}; static int at24cxx_init(void)
{
i2c_add_driver(&at24cxx_driver);
return ;
} static void at24cxx_exit(void)
{
i2c_del_driver(&at24cxx_driver);
} module_init(at24cxx_init);
module_exit(at24cxx_exit); MODULE_LICENSE("GPL");
i2c设备驱动程序
驱动13.i2c设备驱动程序的更多相关文章
- 驱动05.lcd设备驱动程序
参考s3c2410fb.c总结出框架 1.代码分析 1.1 入口函数 int __devinit s3c2410fb_init(void) { return platform_driver_regis ...
- linux设备驱动程序-i2c(0)-i2c设备驱动源码实现
(基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...
- linux设备驱动程序-i2c(1):i2c总线的添加与实现
linux设备驱动程序-i2c(1):i2c总线的添加与实现 (基于4.14内核版本) 在上一章节linux设备驱动程序-i2c(0)-i2c设备驱动源码实现中,我们演示了i2c设备驱动程序的源码实现 ...
- linux设备驱动程序--串行通信驱动框架分析
linux 串行通信接口驱动框架 在学习linux内核驱动时,不论是看linux相关的书籍,又或者是直接看linux的源码,总是能在linux中看到各种各样的框架,linux内核极其庞杂,linux各 ...
- Linux驱动之I2C总线设备以及驱动
[ 导读] 本文通过阅读内核代码,来梳理一下I2C子系统的整体视图.在开发I2C设备驱动程序时,往往缺乏对于系统整体的认识,导致没有一个清晰的思路.所以从高层级来分析一下I2C系统的设计思路,将有助于 ...
- 乾坤合一~Linux设备驱动之I2C核心、总线以及设备驱动
我思念的城市已是黄昏 为何我总对你一往情深 曾经给我快乐 也给我创伤 曾经给我希望 也给我绝望 我在遥远的城市 陌生的人群 感觉着你遥远的忧伤 我的幻想 你的忧伤,像我的的绝望,那样漫长,,,,,这是 ...
- Linux 驱动框架---i2c驱动框架
i2c驱动在Linux通过一个周的学习后发现i2c总线的驱动框架还是和Linux整体的驱动框架是相同的,思想并不特殊比较复杂的内容如i2c核心的内容都是内核驱动框架实现完成的,今天我们暂时只分析驱动开 ...
- linux驱动之I2C
include/linux/i2c.h struct i2c_msg;struct i2c_algorithm;struct i2c_adapter;struct i2c_client;struct ...
- Linux I2C设备驱动编写(二)
在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c_client.三者的关系也在上一节进行了描述.应该已经算是对Linux I2C子系统有了初步 ...
随机推荐
- python class 巩固
class 类定义 语法格式如下: class ClassName: <statement-1> ... <statement-N> 类属性与方法 属性 操作属性 getatt ...
- Html5_css
CSS 在标签上设置style属性: background-color: #2459a2; height: 48px; ... 编写css样式: 1. 标签的style属性 2. 写在head里面 s ...
- nrf52裸机学习——GPIO操作
/** * @brief Function for writing a value to a GPIO pin. * * Note that the pin must be configured as ...
- 自动设置IP地址bat脚本
自动获取IP及DNS: netsh interface ip set address name="本地连接" source=dhcpnetsh interface ip set d ...
- 线段树: CDOJ1598-加帕里公园的friends(区间合并,单点更新)
加帕里公园的friends Time Limit: 3000/1000MS (Java/Others) Memory Limit: 131072/131072KB (Java/Others) 我还有很 ...
- ACM-ICPC 2016 Qingdao Preliminary Contest G. Sort
Recently, Bob has just learnt a naive sorting algorithm: merge sort. Now, Bob receives a task from A ...
- Cplex: MIP Control Callback Methods
*本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 本文主要归纳了Cplex的Control callback常用的方法. 目录 NodeCallback SolveCallback Us ...
- ubuntu12.04 ppa安装pidgin
sudo apt-get update sudo apt-get dist-upgrade sudo add-apt-repository ppa:pidgin-developers/ppa按下回车 ...
- 函数名&函数名取地址
有时看到如下的代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /*****************************/ #includ ...
- #1 add life to static pages && connect to MySQL
由于实验室 Project 中需要用到PHP, 之前也没接触过 PHP, 因此把 编程入门 <Head Fist PHP & MySQL >找来花了四五天快速过了一遍. 现在想把书 ...