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