Search code examples
embedded-linuxyoctokernel-modulebitbake

Unable to add a simple kernel-module to Yocto image


Goal

I want to add a touchscreen driver available in the linux kernel source tree to my Yocto image (The link takes you to goodix.c). I basically need to add it as a kernel module.

Solution

I follow the Incorporating Out-of-Tree Modules section of the Yocto Mega Manual. I base mine off their example kernel-module recipe, called hello-mod.

  1. In recipe goodix-9271_0.1.bb: RPROVIDES_${PN} = "kernel-module-goodix"
  2. In layer.conf: MACHINE_EXTRA_RDEPENDS += "kernel-module-goodix"

Problem

My build simply consistently fails in do_rootfs with:

Error: 
 Problem: package packagegroup-base-1.0-r83.imx6ul_var_dart requires packagegroup-machine-base, but none of the providers can be installed
  - package packagegroup-base-extended-1.0-r83.imx6ul_var_dart requires packagegroup-base, but none of the providers can be installed
  - package packagegroup-machine-base-1.0-r83.imx6ul_var_dart requires kernel-module-goodix, but none of the providers can be installed
  - conflicting requests
  - nothing provides kernel-module-goodix-5.4.3-imx6ul+gb40ccfdb73ea needed by goodix-9271-0.1-r0.imx6ul_var_dart
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

What I cannot understand after reading the documentation on this section is why this error is happening. I tried adjusting the recipe names (removing the kernel-module prefix, etc) but nothing seems to work. What is going wrong?


Source

inherit module logging

# Driver for Goodix touchscreens
SUMMARY = "Generic driver for Goodix touchscreens"
DESCRIPTION = "Support for Goodix 1151, 5663, 5688, 917S, 9286, 911, 9271, 9110, 927, 928, 912, 9147, and 967 touchscreens"

# License
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"

# Compatibility
COMPATIBLE_MACHINE = "(imx)"

# Package name 
RPROVIDES_${PN} = "kernel-module-goodix"

# Source
S = "${WORKDIR}"
SRC_URI = "file://Makefile \
           file://goodix.c"

# Functions

do_install() {
    bbwarn "Installing Goodix kernel module ..."
    bbwarn "KERNEL_SRC = ${KERNEL_SRC}"
    bbwarn "KERNEL_VERSION = ${KERNEL_VERSION}"
    bbwarn "WORKDIR = ${WORKDIR}"
    cd ${S}
    xz goodix.ko
    install --verbose -d ${D}/lib/modules/${KERNEL_VERSION}/kernel/drivers/input/touchscreen
    install --verbose -m 0644 goodix.ko.xz ${D}/lib/modules/${KERNEL_VERSION}/kernel/drivers/input/touchscreen
}

# Reference included files
FILES_${PN} = "/lib/modules/${KERNEL_VERSION}/kernel/drivers/input/touchscreen/*"

Edits

  1. The error basically says that kernel-module-goodix-5.3.4-imx6ul+gb40ccfdb73ea isn't provided. I didn't name my package that way though. So why is it looking for something with the suffix 5.3.4-imx6ul+gb40ccfdb73ea there?

Edit (Solution)

For anyone reading this who isn't satisfied by the accepted answer. Just know that what was wrong with my original recipe was that I wasn't naming my actual recipe "kernel-module-<name>.bb". That was actually what was required.


Solution

  • I have created a recipe for an UART Bluetooth driver before and it works fine for me, here is the recipe:

    #
    # FNLINK BLUETOOTH 8822 KERNEL DRIVER
    #
    
    LICENSE = "CLOSED"
    LIC_FILES_CHKSUM = ""
    
    SRC_URI = "file://uart_bt.zip"
    
    S = "${WORKDIR}/bluetooth_uart_driver"
    
    inherit module
    
    EXTRA_OEMAKE_append_task-install = " -C ${STAGING_KERNEL_DIR} M=${S}"
    EXTRA_OEMAKE += "KDIR=${STAGING_KERNEL_DIR}"
    

    Change S to "bluetooth_uart_driver" because the zip file contains that directory with the content:

    ifneq ($(KERNELRELEASE),)
        obj-m       := hci_uart.o
        hci_uart-y  := hci_ldisc.o hci_h4.o hci_rtk_h5.o rtk_coex.o
        #EXTRA_CFLAGS += -DDEBUG
    
    else
        PWD := $(shell pwd)
        KVER := $(shell uname -r)
        KDIR := /lib/modules/$(KVER)/build
    
    all:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    clean:
        rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a
    
    endif
    

    This works well for me, and the .ko file is generated and shipped into /lib/modules/${KVER}/extra , so you can override the do_install function and install it where you want.

    Simple Test:

    I downloaded the goodix.c driver and created a custom recipe for it with this Makefile (I modified my old BT Makefile):

    ifneq ($(KERNELRELEASE),)
        obj-m       := goodix.o
    
    else
        PWD := $(shell pwd)
        KVER := $(shell uname -r)
        KDIR := /lib/modules/$(KVER)/build
    
    all:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    clean:
        rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a
    
    endif
    

    My recipe:

    |meta-test/
        |--> recipes-driver/
             |--> files/
                  |--> goodix.c
                  |--> Makefile
             |--> goodix-driver_0.1.bb
    

    goodix-driver_0.1.bb:

    LICENSE = "CLOSED"
    LIC_FILES_CHKSUM = ""
    SRC_URI = "file://goodix.c file://Makefile"
    S = "${WORKDIR}"
    inherit module
    EXTRA_OEMAKE_append_task-install = " -C ${STAGING_KERNEL_DIR} M=${S}"
    EXTRA_OEMAKE += "KDIR=${STAGING_KERNEL_DIR}"
    

    With this in a simple poky build I was able to generate the .ko file.

    Note:

    If goodix.c is present in your upstream Linux kernel, which means you can find it in:

    tmp/work/.../linux-../../git/drivers/input/touchscreen/goodix.c
    

    which means you can just patch it without creating a whole recipe for it, you just edit it directly and then go back to git folder and :

    git add drivers/input/touchscreen/goodix.c
    git commit -m "My-updates"
    git format-patch -1 -o /path/to/meta-custom/recipes-kernel/linux/files
    

    Now, in /path/to/meta-custom/recipes-kernel/linux/linux-xx_%.bbappend add:

    SRC_URI_append = " file://My-updates.patch"
    

    Now, do not forget to activate it via menuconfig and add its flag to the kernel defconfig file so it gets compiled and shipped within the rootfs.