Search code examples
driverlinux-device-driveryocto

Yocto WiFi Driver


I am trying to have Yocto build a third-party driver and include it in my image. Specifically the driver for an Edimax EW-7811Un-V2 USB WiFi adapter.

I have got the driver working on the target machine by manually compiling and calling depmod, so I'm confident that it is supported.

Initially I tried replicating the manual process using the following .bb file:

DESCRIPTION="Driver for Edimax EW-7811Un-V2"
LICENSE="CLOSED"
LIC_FILES_CHKSUM=""
DEPENDS=""
INHIBIT_PACKAGE_STRIP="1"

SRC_URI = "file://ew7811un-v2-1.0.1.3.zip"

S = "${WORKDIR}/ew7811un-v2-1.0.1.3"

do_compile {
    oe_runmake_clean
    oe_runmake
}

do_install() {
    # This fails as Makefile does not respect DESTDIR
    # There is an INSTALL_PREFIX variable, but it is not used in the install command
    #oe_runmake install DESTDIR=${D}

    # Instead call the install command directly
    install -d ${D}/lib/modules/4.14.98-2.2.0+gecb7f95/kernel/drivers/net/wireless
    install -p -m 644 8188eu.ko ${D}/lib/modules/4.14.98-2.2.0+gecb7f95/kernel/drivers/net/wireless
}

do_package_qa[noexec] = "1"

FILES_${PN} = "/lib/modules/4.14.98-2.2.0+gecb7f95/kernel/drivers/net/wireless/8188eu.ko"

This does not error but trying to load the module with modprobe and insmod on the target suggests the module was built for the wrong kernel version. Checking log.do_compile shows that make is run against kernel version 4.15.0-142-generic (the kernel version of the host machine) rather than 4.14-sumo.

I have also tried following the hello-mod_0.1.bb example:

DESCRIPTION="Driver for Edimax EW-7811Un-V2"
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
DEPENDS = ""

inherit module

SRC_URI = "file://ew7811un-v2-1.0.1.3.zip"

S = "${WORKDIR}/ew7811un-v2-1.0.1.3"

RPROVIDES_${PN} += "kernel-module-${PN}"

but this fails to compile at all. Output includes recipe for target 'sub-make' failed and I get a long list of errors beginning with warnings that __LINUX_ARCH_ARM__ is not defined. Again this seems to use the host machine kernel headers rather than the target, even though bitbake outputs DISTRO_VERSION = "4.14-sumo".

Which is the correct way to add a driver to my image? Why are the host machine kernel headers being used rather than the targets?


Solution

  • I am now convinced that the correct method for building an out-of-tree kernel module is to follow the structure of module.bbclass

    The .bb file in the question did not work because the provided Makefile did not follow expected conventions. In particular I had to set the kernel source directory KSRC (rather than KERNEL_SRC specified in module.bbclass) in order to use the target kernel headers. I also had to overwrite the do_install() method as the Makefile did not provide a modules_install target, and the install target failed to create directories. I ended up with the following .bb file:

    DESCRIPTION = "Driver for Edimax EW-7811Un-V2"
    LICENSE = "CLOSED"
    LIC_FILES_CHKSUM = ""
    DEPENDS = ""
    
    inherit module
    
    EXTRA_OEMAKE += "KSRC=${STAGING_KERNEL_DIR}"
    
    SRC_URI = "file://ew7811un-v2-1.0.1.3.zip"
    
    S = "${WORKDIR}/ew7811un-v2-1.0.1.3"
    
    do_install() {
        unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
        install -d ${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/wireless
        install -p -m 644 8188eu.ko ${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/wireless
    
        if [ ! -e "${B}/${MODULES_MODULE_SYMVERS_LOCATION}/Module.symvers" ] ; then
            bbwarn "Module.symvers not found in ${B}/${MODULES_MODULE_SYMVERS_LOCATION}"
            bbwarn "Please consider setting MODULES_MODULE_SYMVERS_LOCATION to a"
            bbwarn "directory below B to get correct inter-module dependencies"
        else
            install -Dm0644 "${B}/${MODULES_MODULE_SYMVERS_LOCATION}"/Module.symvers ${D}${includedir}/${BPN}/Module.symvers
            # Module.symvers contains absolute path to the build directory.
            # While it doesn't actually seem to matter which path is specified,
            # clear them out to avoid confusion
            sed -e 's:${B}/::g' -i ${D}${includedir}/${BPN}/Module.symvers
        fi
    }
    
    RPROVIDES_${PN} += "kernel-module-${PN}"