TL;DR:
当我尝试编译 USB DAQ 设备的驱动程序时,我重新配置了内核。驱动程序拒绝在默认发行版的内核下编译,但一切都可以与我调整的内核一起使用。
该驱动程序由 2 个内核模块组成。我知道我更改了哪些选项,但我想知道哪个特定配置选项启用了我的驱动程序。有什么方法可以解决这个问题,而无需尝试(配置和编译内核)所有可能的选项组合?
更长的故事:
我有一个 Advantech USB-4702 DAQ 设备,它附带了适用于各种发行版的驱动程序,例如 openSUSE 11.4。它必须从源代码编译,并且在受支持的发行版上编译得很好(我尝试了带有内核 2.6.37.6-24-desktop 的 openSUSE 11.4 32 位)。
当我尝试让它在 SLES 11 SP 3(64 位,内核 3.0.76-0.11-default)下工作时,出现编译错误。其中之一是由源代码中的这段代码引起的:
#ifndef CONFIG_USB
# error "This driver needs to have USB support."
#endif
因此,我查看了正在运行的内核的配置选项(来自/proc/config.gz),发现 CONFIG_USB 已启用(我猜如果禁用它,我将无法使用 USB 键盘和鼠标)。然后我开始使用内核配置并启用其中的一些(有些作为模块)。我编译了内核,安装了它,然后重新启动。然后驱动程序编译后没有任何错误或警告,我现在可以使用该设备了。
问题是,如何找出“启用”驱动程序编译的特定选项?我知道更改了哪些选项,但我不想启用驱动程序不需要的任何内容。我不想使用每种可能的选项组合来配置和编译内核。
答案1
我假设,有问题的驱动程序被编译为模块。如果您还将先决条件构建为模块,则可以轻松找到它们。所有模块及其相应的选项都记录在内核 makefile 中。所以你可以用 grep 来查找模块名称。
但首先,您需要找出您的驱动程序依赖于哪些模块。因此,发出 alsmod
并搜索您的驱动程序,特别是在 Column 中Used by
。我以使用驱动程序为例rt2800usb
。
$ lsmod | grep rt2800usb
rt2800usb 15392 0
rt2x00usb 8306 1 rt2800usb
rt2800lib 59262 1 rt2800usb
rt2x00lib 34431 3 rt2x00usb,rt2800lib,rt2800usb
usbcore 146570 7 rt2x00usb,rt2800usb
这告诉我我的驱动程序需要模块rt2x00usb
、rt2800lib
和rt2x00lib
。usbcore
现在我在 Makefile 中搜索它们。注意.o
搜索字符串中的前导空格和尾随空格
$ fgrep -r --include=Makefile ' usbcore.o'
drivers/usb/core/Makefile:obj-$(CONFIG_USB) += usbcore.o
$ grep -Pr --include=Makefile ' rt2(x|8)00(usb|lib)\.o'
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2800_LIB) += rt2800lib.o
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2800USB) += rt2800usb.o
在那里我们有构建这些模块所需的配置选项。如果您无法立即找到罪魁祸首,请尝试更深入地搜索依赖项的依赖项...如果您能猜出名称,这可能对内置对象也有帮助(与模块相反)。
(本文中的所有命令行输出都经过稍微压缩和重新格式化,以提高可读性。)
答案2
经过进一步的实验,我可以证实我在评论之一中提出的主张:该 CONFIG_USB
选项必须具有价值Y
;m
是不足够的”。顺便说一下,openSUSE 11.4 中的内核Y
默认有它,SLES11SP3 中的内核有m
.
遗憾的是错误信息并没有说清楚。
设置它的一个简单方法是通过make menuonfig
,然后选择Y
该选项支持主机端USB在下面设备驱动程序 -> USB 支持。
答案3
make config
当您使用(或make menuconfig
或)时看到的信息和问题make xconfig
来自内核配置源树中的文件。他们有很多;尝试find . -name Kconfig
从树的顶部看一下。
以下是 3.10.1/drivers/misc/Kconfig 中的示例:
config AD525X_DPOT_I2C
tristate "support I2C bus connection"
depends on AD525X_DPOT && I2C
help
Say Y here if you have a digital potentiometers hooked to an I2C bus.
To compile this driver as a module, choose M here: the
module will be called ad525x_dpot-i2c.
有一些关于领域的讨论这里,但如果你使用得足够多,就不难看出发生了什么menuconfig
;通常会在“帮助”中给出一个版本,如果您使用搜索功能(按/
),返回的点击也会报告这些内容。例如,通过make menuconfig
搜索“AD525”:
│ Symbol: AD525X_DPOT_I2C [=n] │
│ Type : tristate │
│ Prompt: support I2C bus connection │
│ Location: │
│ -> Device Drivers │
│ -> Misc devices │
│ (1) -> Analog Devices Digital Potentiometers (AD525X_DPOT [=n]) │
│ Defined at drivers/misc/Kconfig:34 │
│ Depends on: AD525X_DPOT [=n] && I2C [=y]
“Tristate”表示选项是yes/no/module,还有“bool”和“int”类型。请注意,此处的“取决于”(对应于 Kconfig 文件中的源)包括指示我是否选择了正确的依赖项 ( [=n]
[=y]
)。这是非常有用的信息,因为有些事情甚至不会出现为选择直到您选择正确的先决条件。
理想情况下,编写模块的人包括内核配置数据,以便它可以无缝地插入到源代码树中并通过正常方式进行配置。看看它,您应该能够跟踪依赖关系。