忘记了在哪本书上看到过,说必须给 I2C 设备驱动的 id 表数组添加上一个空元素作为最后一个元素,就像下面的代码所展示的那样:
-
struct i2c_device_id {
-
char name[I2C_NAME_SIZE];
-
kernel_ulong_t driver_data; /* Data private to the driver */
-
}
-
-
-
static const struct i2c_device_id rt5677_i2c_id[] = {
-
{ "rt5677", 0 },
-
{ } // 末尾需要是一个空元素
-
};
-
-
-
struct i2c_driver rt5677_i2c_driver = {
-
.driver = {
-
.name = "rt5677",
-
.owner = THIS_MODULE,
-
#ifdef CONFIG_PM
-
.pm = &rt5677_pm_ops,
-
#endif
-
#ifdef RTACPI_I2C
-
.acpi_match_table = ACPI_PTR(rt5677_acpi_match),
-
#endif
-
},
-
.probe = rt5677_i2c_probe,
-
.remove = rt5677_i2c_remove,
-
.shutdown = rt5677_i2c_shutdown,
-
.id_table = rt5677_i2c_id, // 指定id_table
-
};
那么原因是什么呢?这样的声明方式
一定和它的使用方式有关,所以我们一起在代码中看看 id_table[] 数组被使用的地方:
-
/**
-
* hda_match - bind hda device to hda driver.
-
* @dev: device.
-
* @drv: driver.
-
*
-
*/
-
static int soc_hda_match(struct device *dev, struct device_driver *drv)
-
{
-
struct snd_soc_hda_device *pdev = to_soc_hda_device(dev);
-
struct snd_soc_hda_driver *pdrv = to_soc_hda_driver(drv);
-
-
/* Then try to match against the id table */
-
if (pdrv->id_table)
-
return soc_hda_match_id(pdrv->id_table, pdev) != NULL; // 传入 id_table 指针进行匹配
-
-
/* fall-back to driver name match */
-
return (strcmp(pdev->name, drv->name) == 0);
-
}
从上方我们看到 id_table 被 soc_hda_match_id() 函数作为入口参数使用,继续深入查看该函数中的操作:
-
static const struct snd_soc_hda_device_id *soc_hda_match_id(
-
const struct snd_soc_hda_device_id *id,
-
struct snd_soc_hda_device *pdev)
-
{
-
while (id->name[0]) { // 如果 name 不为空,则执行下列匹配
-
if (pdev->id == id->id) {
-
pdev->id_entry = id;
-
return id;
-
} else if (strcmp(pdev->name, id->name) == 0) {
-
pdev->id_entry = id;
-
return id;
-
}
-
id++; // 继续处理 id_table 中的下一个元素
-
}
-
return NULL;
-
}
看到这里,原因就很清楚了:while语句只有在检测到 id_table 中某一个元素的 name 成员为空时,才会跳出循环,所以在定义 id_table 时必须使用一个空元素{}来作为结束标记。
这个用法就类似字符数组必须使用\0字符来作为结束符一样(或者表述为:字符串必须以\0字符结尾),否则程序在处理字符串时将不知何时终止而出现错误。
阅读(4426) | 评论(0) | 转发(0) |