2025-03-12
很好奇I2C设备是如何与驱动进行匹配的吧?一般是通过设备树文件来描述I2C从设备的信息,例如名称和地址等。驱动通过和名称与从设备进行匹配。不过下面的例子不使用设备树文件,而是手动匹配从设备。具体方法看测试
章节。
// simple.c
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
struct my_data {
char name[32];
int i;
};
static struct my_data data_1 = {
.name = "device a",
.i = 1,
};
static struct my_data data_2 = {
.name = "device b",
.i = 2,
};
static struct i2c_device_id my_ids[] = {
{"device-a", (size_t)&data_1},
{"device-b", (size_t)&data_2},
{},
};
MODULE_DEVICE_TABLE(i2c, my_ids);
static int _probe(struct i2c_client *client) {
pr_info("simple_probe\n");
const struct i2c_device_id *id = i2c_match_id(my_ids, client);
if (!id) {
pr_err("i2c_match_id found\n");
return -ENODEV;
}
struct my_data *data = (struct my_data *)id->driver_data;
if (data) {
pr_info("%s data->i = %d\n", data->name, data->i);
} else {
pr_err("id->driver_data is null\n");
}
return 0;
}
static void _remove(struct i2c_client *client) { pr_info("simple_remove\n"); }
static struct i2c_driver my_driver = {
.probe = _probe,
.remove = _remove,
.id_table = my_ids,
.driver =
{
.name = "my-i2c-driver",
},
};
module_i2c_driver(my_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple kernel module");
#!/bin/sh
top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build
obj-m += simple.o
all:
make -C $(kernel-dir) modules M=$(top-dir)
clean:
rm -f *.o *.ko *.mod *.mod.c *.order *.symvers *.dtbo
make -C $(kernel-dir) clean m=$(top-dir)
编译程序:make
安装驱动:insmod simple.ko
查看i2c总线:i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: 10 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
添加i2c从设备:echo device-a 0x10 > /sys/bus/i2c/devices/i2c-0/new_device
查看输出:dmesg
[112662.497446] simple_probe
[112662.497457] device a data->i = 1
[112662.497477] i2c i2c-0: new_device: Instantiated device device-a at 0x10
移除i2c从设备:echo 0x10 > /sys/bus/i2c/devices/i2c-0/delete_device
移除驱动:rmmod simple.ko