在一个驱动程序模块中处理多个 i2c_clients(使用 sysfs)

Handling multiple i2c_clients in one driver module (with sysfs)

我想为 tmp102 温度传感器创建内核驱动程序。 在一个项目中,我只有 1 个传感器,而在另一个项目中,我有 2 个传感器。我希望我的内核模块能够支持 N​​ 个传感器,而不是固定数量。我在管理超过 1 个结构 i2c_client 并为每个结构创建 sysfs 条目时遇到问题。我是这样做的:

  1. probe() 函数中,我为我提供 I2C_BOARD_INFO() 的每个设备得到 struct i2c_client*

  2. 然后我 kobject_create_and_add("tmp102", kernel_kobj) 获取 sysfs.

  3. 中模块的主目录
  4. 对于我正在创建的每个设备 sysfs_create_group(),它获取指向静态创建的属性的指针。这些属性将 (*show)()(*store)() 指针设置为静态函数,例如

    static ssize_t tmp102_sysfs_thigh_get_one(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
    

在这个函数中我想通过I2C读取。问题是......我不知道如何获取设备的 struct i2c_client * 应该以某种方式 linked 到这个 sysfs 条目,以及I2C地址在那里!

我应该如何正确地 "link" i2c_client 与 sysfs 条目,以便我可以在函数中获取 I2C 地址?

理想情况下,我希望只有一组函数(每个属性一个)。 sysfs 树应该是这样的:

  /sysfs/kernel/tmp102
  |
  |-> <hex i2c address, e.g. /48>
  |   |
  |   |-> temperature   
  |
  |   
  |-> /49
      |
      |-> temperature

我希望两个 'temperature' 属性使用相同的函数,它能够确定它应该写入的 I2C 地址。

或者我的架构完全错误?如果是这样,对于需要处理多个 i2c_client 的驱动程序来说应该是什么样子?

编辑:

我决定使用 struct device_attribute 而不是常规的 attribute。据我了解,使用常规属性时,获取struct device指针并不容易,struct i2c_client也是如此。他们不容易 "linked" 和来自 /sys/kernelkobjects,我需要在这个项目中拥有我的属性。 device_attributes 可以在 /sys/devices 中找到 - 我使用了 sysfs_create_group 并且 link 使用 device_attribute 组编辑了我设备的 kobject。我使用了 sysfs_create_link,并且 link 使用 /sys/kernel/tmp102 编辑了我设备的 kobject。这样我就可以为每个设备创建一个文件夹 (link),它指向 /sys/devices 中的原始属性文件夹。

首先,您应该知道已经有一个具有 sysfs 接口的 tmp102 内核驱动程序。看看 drivers/hwmon/tmp102.c.

现在,对于您的问题,您有一个 struct kobject 传递给您的 sysfs 回调。您可以调用 kobj_to_dev() 来获取指向设备的指针。然后,例如,您可以使用 dev_get_drvdata() 获取指向您自己的私有结构的指针,该结构将包含指向 i2c 客户端的指针。不要忘记先在您的探测器中使用 dev_set_drvdata() 进行设置。

您可以在 drivers/rtc/rtc-ds1343.c 中找到示例,但它使用的是 spi_driver。