Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301460
  • 博文数量: 41
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 476
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-01 19:08
个人简介

Android/Linux/音频/驱动

文章分类

全部博文(41)

文章存档

2017年(21)

2016年(20)

我的朋友

分类: 其他平台

2017-06-26 15:51:02


  忘记了在哪本书上看到过,说必须给 I2C 设备驱动的 id 表数组添加上一个空元素作为最后一个元素,就像下面的代码所展示的那样:

  1. struct i2c_device_id {
  2.     char name[I2C_NAME_SIZE];
  3.     kernel_ulong_t driver_data; /* Data private to the driver */
  4. }


  5. static const struct i2c_device_id rt5677_i2c_id[] = {
  6.     { "rt5677", 0 },
  7.     { } // 末尾需要是一个空元素
  8. };


  9. struct i2c_driver rt5677_i2c_driver = {
  10.     .driver = {
  11.         .name = "rt5677",
  12.         .owner = THIS_MODULE,
  13. #ifdef CONFIG_PM
  14.         .pm = &rt5677_pm_ops,
  15. #endif
  16. #ifdef RTACPI_I2C
  17.         .acpi_match_table = ACPI_PTR(rt5677_acpi_match),
  18. #endif
  19.     },
  20.     .probe = rt5677_i2c_probe,
  21.     .remove = rt5677_i2c_remove,
  22.     .shutdown = rt5677_i2c_shutdown,
  23.     .id_table = rt5677_i2c_id, // 指定id_table
  24. };
  那么原因是什么呢?这样的声明方式一定和它的使用方式有关,所以我们一起在代码中看看 id_table[] 数组被使用的地方:
  1. /**
  2.  * hda_match - bind hda device to hda driver.
  3.  * @dev: device.
  4.  * @drv: driver.
  5.  *
  6.  */
  7. static int soc_hda_match(struct device *dev, struct device_driver *drv)
  8. {
  9.     struct snd_soc_hda_device *pdev = to_soc_hda_device(dev);
  10.     struct snd_soc_hda_driver *pdrv = to_soc_hda_driver(drv);

  11.     /* Then try to match against the id table */
  12.     if (pdrv->id_table)
  13.         return soc_hda_match_id(pdrv->id_table, pdev) != NULL; // 传入 id_table 指针进行匹配

  14.     /* fall-back to driver name match */
  15.     return (strcmp(pdev->name, drv->name) == 0);
  16. }
  从上方我们看到 id_table 被 soc_hda_match_id() 函数作为入口参数使用,继续深入查看该函数中的操作:
  1. static const struct snd_soc_hda_device_id *soc_hda_match_id(
  2.             const struct snd_soc_hda_device_id *id,
  3.             struct snd_soc_hda_device *pdev)
  4. {
  5.     while (id->name[0]) { // 如果 name 不为空,则执行下列匹配
  6.         if (pdev->id == id->id) {
  7.             pdev->id_entry = id;
  8.             return id;
  9.         } else if (strcmp(pdev->name, id->name) == 0) {
  10.                 pdev->id_entry = id;
  11.                 return id;
  12.         }
  13.         id++; // 继续处理 id_table 中的下一个元素
  14.     }
  15.     return NULL;
  16. }
  看到这里,原因就很清楚了:while语句只有在检测到 id_table 中某一个元素的 name 成员为空时,才会跳出循环,所以在定义 id_table 时必须使用一个空元素{}来作为结束标记。这个用法就类似字符数组必须使用\0字符来作为结束符一样(或者表述为:字符串必须以\0字符结尾),否则程序在处理字符串时将不知何时终止而出现错误。 


阅读(3534) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~