We're hiring!
*

Quick hack: Patching kernel modules using DKMS

Frederic Danis avatar

Frederic Danis
May 05, 2021

Share this post:

Reading time:

Dynamic Kernel Module Support (DKMS) is a framework that is mostly used to build and install external kernel modules. However, it can also be used to install a specif patch to the modules of the current kernel, for example, to apply a specific fix.

For example, when PipeWire 0.3.20 was released earlied this year, it brought support for the mSBC codec which I had added, and which works natively or through the external programs oFono or hsphfpd, when connected to a Bluetooth Headset through the HFP profile.

Unfortunately, for kernels 5.8 up to 5.10.17, this support does not work with USB Bluetooth chipsets from vendors other than Intel.

While the fix was simple and has since been backported to the LTS kernels, if you are like me and are running a Linux distribution based on a non-LTS kernel, for example Ubuntu 20.04 with kernel 5.8, you will not be able to benefit from this fix. That is, unless you use DKMS to patch the kernel's Bluetooth module.

Here's how to do it, which you can also apply to other modules when needed.

Limitations

Note that you can not, and should not, try to patch the header files of the kernel, so the original commit may need some tweaks to apply correctly.

This is not the case here, as the patch applies to only one file.

Let's begin.

Create DKMS module

DKMS is looking for a configuration file dkms.conf in /usr/src/<module>-<version>.

So let's create the directory and copy the patch file to it:

$ sudo mkdir /usr/src/btusb-0.8

Then edit the /usr/src/btusb-0.8/dkms.conf with the following:

PACKAGE_NAME="btusb"
PACKAGE_VERSION="0.8"
BUILT_MODULE_NAME[0]="btusb"
DEST_MODULE_LOCATION[0]="/updates/dkms/"
AUTOINSTALL="yes"
REMAKE_INITRD="yes"
PRE_BUILD="dkms-patchmodule.sh drivers/bluetooth"

Retrieve the fix

We need to get the original fix in a way that allows us apply it to the kernel source. The best way is to get it directly from kernel.org:

$ wget -O /usr/src/btusb-0.8/Bluetooth-btusb-Always-fallback-to-alt-1-for-WBS.patch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/patch/drivers/bluetooth?id=834d68fa4f8fe82bfd8fded8fe5b7b064d12407a

or if you already have the git kernel tree:

$ git format-patch 517b693351a -1 -M -o /usr/src/btusb-0.8 --subject="PATCH"

This patch does not apply directly on 5.8 kernel sources, so the it needs to be tweaked. Replace content of the original /usr/src/btusb-0.8/Bluetooth-btusb-Always-fallback-to-alt-1-for-WBS.patch by:

--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1666,14 +1666,12 @@ static void btusb_work(struct work_struct *work)
 				new_alts = data->sco_num;
 			}
 		} else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) {
-
-			data->usb_alt6_packet_flow = true;
-
-			/* Check if Alt 6 is supported for Transparent audio */
-			if (btusb_find_altsetting(data, 6))
-				new_alts = 6;
-			else
-				bt_dev_err(hdev, "Device does not support ALT setting 6");
+			/* Bluetooth USB spec recommends alt 6 (63 bytes), but
+			 * many adapters do not support it.  Alt 1 appears to
+			 * work for all adapters that do not have alt 6, and
+			 * which work with WBS at all.
+			 */
+			new_alts = btusb_find_altsetting(data, 6) ? 6 : 1;
 		}

 		if (btusb_switch_alt_setting(hdev, new_alts) < 0)

Create the patching script

We now need to create the dkms-patchmodule.sh script to get the kernel module source and patch it.

Unfortunately, Ubuntu does not install the kernel source correctly for HWE, and both the kernel package version and subversion numbers do not directly refer to upstream kernel version and subversion.

During the kernel upgrade the kernelver environment variable is not set, however DPKG_MAINTSCRIPT_PACKAGE contains the kernel image or header package upgraded and we can use it to get the kernel version.

During the module installation, DKMS performs a module version sanity check and does not replace the module if the version of the built module is not greater than the one already installed. So, the module version should be increased.

We therefore need to retrieve the upstream kernel source, extract the module source, increase the version and apply the patch.

Add the file /usr/src/btusb-0.8/dkms-patchmodule.sh with the following content:

#!/bin/bash
# kernelver is not set on kernel upgrade from apt, but DPKG_MAINTSCRIPT_PACKAGE
# contains the kernel image or header package upgraded
if [ -z "$kernelver" ] ; then
  echo "using DPKG_MAINTSCRIPT_PACKAGE instead of unset kernelver"
  kernelver=$( echo $DPKG_MAINTSCRIPT_PACKAGE | sed -r 's/linux-(headers|image)-//')
fi

vers=(${kernelver//./ })   # split kernel version into individual elements
major="${vers[0]}"
minor="${vers[1]}"
version="$major.$minor"    # recombine as needed
# In Debian (and some Debian derivatives), the linux headers are split in
# two packages: an arch-specific and an arch-independent package.
# For example: linux-headers-6.1.0-6-amd64 and linux-headers-6.1.0-6-common.
# The arch-specific Makefile is just a one-line include directive.
makefile=/usr/src/linux-headers-${kernelver}/Makefile
if [ $(wc -l < $makefile) -eq 1 ] && grep -q "^include " $makefile ; then
  makefile=$(tr -s " " < $makefile | cut -d " " -f 2)
fi
subver=$(grep "SUBLEVEL =" $makefile | tr -d " " | cut -d "=" -f 2)

echo "Downloading kernel source $version.$subver for $kernelver"
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v$major.x/linux-$version.$subver.tar.xz

echo "Extracting original source"
tar -xf linux-$version.$subver.tar.* linux-$version.$subver/$1 --xform=s,linux-$version.$subver/$1,.,

# The new module version should be increased to allow the new module to be
# installed during kernel upgrade
echo "Increase module version"
sed -i 's/\(#define VERSION "0\.8\)/\1\.1/' btusb.c

for i in `ls *.patch`
do
  echo "Applying $i"
  patch < $i
done

Build and install the patched module

This will build and install the patched module:

$ sudo dkms install btusb/0.8

As btusb module is used by multiple other kernel modules, it is easier to reboot now to be able to use your headset to chat with a better sound quality.

Enjoy! :)

Disclaimer

The idea on how to go about patching a module with DKMS is based on Using DKMS to compile patched modules.

Comments (2)

  1. Bruno Alves:
    Jun 30, 2021 at 08:48 PM

    Hello!
    I've tried to patching my Debian 4.19.0-17-amd64 but when I run the command
    sudo dkms install btusb/0.8
    Bash asked me
    "File to patch: "
    I have no idea that file is it, after that appears the message when I press [Y] to skip this patch:
    Error! Bad return status for module build on kernel: 4.19.0-17-amd64 (x86_64) Consult /var/lib/dkms/btusb/0.8/build/make.log for more information.


    Could you tell me what I need to put for this?
    Have a great day!

    Reply to this comment

    Reply to this comment


Add a Comment






Allowed tags: <b><i><br>Add a new comment:


Search the newsroom

Latest Blog Posts

Automatic regression handling and reporting for the Linux Kernel

14/03/2024

In continuation with our series about Kernel Integration we'll go into more detail about how regression detection, processing, and tracking…

Almost a fully open-source boot chain for Rockchip's RK3588!

21/02/2024

Now included in our Debian images & available via our GitLab, you can build a complete, working BL31 (Boot Loader stage 3.1), and replace…

What's the latest with WirePlumber?

19/02/2024

Back in 2022, after a series of issues were found in its design, I made the call to rework some of WirePlumber's fundamentals in order to…

DRM-CI: A GitLab-CI pipeline for Linux kernel testing

08/02/2024

Continuing our Kernel Integration series, we're excited to introduce DRM-CI, a groundbreaking solution that enables developers to test their…

Persian Rug, Part 4 - The limitations of proxies

23/01/2024

This is the fourth and final part in a series on persian-rug, a Rust crate for interconnected objects. We've touched on the two big limitations:…

How to share code between Vulkan and Gallium

16/01/2024

One of the key high-level challenges of building Mesa drivers these days is figuring out how to best share code between a Vulkan driver…

Open Since 2005 logo

We use cookies on this website to ensure that you get the best experience. By continuing to use this website you are consenting to the use of these cookies. To find out more please follow this link.

Collabora Ltd © 2005-2024. All rights reserved. Privacy Notice. Sitemap.