Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

TL;DR:
when I was trying to compile a driver for USB DAQ device I have reconfigured the kernel. The driver refused to compile under the default distro's kernel but everything works with my tweaked kernel.

The driver consists of 2 kernel modules. I know which options I changed but I want to know which particular configuration option enabled my driver. Is there any way how to figure it out without trying (configuring and compiling kernel) every possible combination of the options?

Longer story:
I have an Advantech USB-4702 DAQ device which comes with a driver for various distros, e.g. openSUSE 11.4. It has to be compiled from source and it compiles well on supported distributions (I tried openSUSE 11.4 32bit with kernel 2.6.37.6-24-desktop).

When I was trying to get it work under SLES 11 SP 3 (64bit, kernel 3.0.76-0.11-default) I got compile errors. One of them was caused by this snippet in the source:

#ifndef CONFIG_USB
#  error "This driver needs to have USB support."
#endif

So I took a look at the configuration options of the running kernel (from /proc/config.gz) and found CONFIG_USB to be enabled (I guess I would not be able to use my USB keyboard and mouse if it was disabled). Then I started to play with the kernel configuration and enabled (some as modules) some of them. I compiled the kernel, installed it, rebooted. Then the driver compiled without any errors or warnings and I am able to use the device now.

The question is, how can I find out which particular option "enabled" compilation of the driver? I know which options were changed, but I don't want to enable anything that is not necessary for the driver. And I don't want to go through configuring and compiling the kernel with every possible combination of the options.

share|improve this question
    
AFAIK, not programatically. I'm no expert by far, but it seems like the most you could do is make an educated guess at which one worked. Or I guess you could grep through the kernel tree looking for a config CONFIG_USB, but that might waste more time than it saves. –  strugee Sep 5 '13 at 6:54
    
How many options did you change? Can't you just diff your config file against the stock config? –  Zoredache Sep 5 '13 at 7:40
    
About 10. Now I'm reviewing the diff and I see that I also changed CONFIG_USB from 'm' to 'y'. Is it possible that it does cause the #ifndef CONFIG_USB test to fail? –  Peter Kovac Sep 5 '13 at 8:17
add comment

3 Answers 3

up vote 1 down vote accepted

After some further experimenting I can confirm my claim made in one of my comments: the CONFIG_USB option has to have value Y; m is "not enough". Incidentally, the kernel in openSUSE 11.4 has it Y by default and the kernel in SLES11SP3 has m.

It's a pity that the error message does not state it clearly.

An easy way of setting it up is via make menuonfig, then selecting Y for the option Support for host-side USB under Device Drivers -> USB Support.

share|improve this answer
    
With CONFIG_USB set to m, the #error directive protected by #ifndef CONFIG_USB should fail. So it looks like there is a bug in the driver's compilation script (Kbuild) that causes the wrong options to be passed to the compiler in that case. –  Gilles Sep 5 '13 at 21:15
add comment

I assume, the driver in question is compiled as a module. If you also built the prerequisites as modules, you can easily find them. All modules and their corresponding options are noted in the kernel makefiles. So you can just grep these for the module name.

But first, you need to find out, which modules your driver depends on. So issue a lsmod and search for your driver, especially in the Column Used by. I, for example use the rt2800usb driver.

$ 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

This tells me that my driver needs the modules rt2x00usb, rt2800lib, rt2x00lib and usbcore. Now I search the Makefiles for them. Note the leading space and trailing .o in the search strings

$ 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

And there we have the config options needed to build those modules. If you cannot instantly find the culprit, try to go a level deeper and search for the dependencies of the dependencies... If you can guess the name, this may help for built-in objects, too (contrary to modules).

(All command line outputs in this post were slightly condensed and reformatted for better readability.)

share|improve this answer
add comment

The info and questions you see when you use make config (or make menuconfig or make xconfig) comes from Kconfig files in the source tree. There's a lot of them; try find . -name Kconfig from the top of the tree and have a look at one.

Here's an example from 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.

There's some discussion of the fields here, but it is not hard to see what's going on if you've used menuconfig enough; a version of this is usually given with the "help", and if you use the search function (press /) the hits returned report this stuff too. E.g., from make menuconfig searching for "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" indicates the options are yes/no/module, there's also "bool" and "int" types. Notice the "Depends on" here (which corresponds to the source from the Kconfig file) includes an indication of whether I have the correct dependencies selected ([=n] [=y]). This is pretty useful information since some things won't even appear as choices until you select the right prereqs.

Ideally, the people who wrote your module included Kconfig data so that it could be seemlessly inserted into the source tree and configured via normal means. Have a look for that and you should be able to trace the dependencies.

share|improve this answer
    
A Kconfig file is included in the source package. Unfortunately it is not very helpful, because it is a copy of drivers/misc/c2port/Kconfig. There is a Silicon Labs chip on the device, so I guess the manufacturer wanted to require C2PORT to be enabled. However I had it enabled as module in the stock kernel too. On the other hand, if I had this disabled the device probably won't work. –  Peter Kovac Sep 5 '13 at 13:06
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.