Compiling your own WSL2 kernel

Olof Astrand
4 min readJul 11, 2024

If using usbip, to get access to USB devices within WSL2, you might want to utilize your USB camera. Unfortunately, the default configuration provided by Microsoft does not include support for USB video devices. However, you can overcome this limitation by compiling your own custom kernel with the necessary support enabled. Here’s a detailed guide to help you through the process:

Uning usbip (ver > 4.0)

https://github.com/dorssel/usbipd-win


usbipd list
Connected:
BUSID VID:PID DEVICE STATE
2–6 045e:0779 Microsoft LifeCam HD-3000, Microsoft® LifeCam HD-3000 Not shared

usbipd attach --wsl --busid 2-6

Now you should see the device in wsl with i.e. lsusb

Bus 001 Device 002: ID 045e:0779 Microsoft Corp. LifeCam HD-3000

However the kernel has not recognized this yet. As one can see by the missing /dev/video* and by looking at the log with >dmesg

On i.e. Ubuntu in WSL2

Install neceseary build tools

$ sudo apt update && sudo apt upgrade -y
$ sudo apt install -y \
build-essential flex bison \
libgtk-3-dev libelf-dev libncurses-dev autoconf \
libudev-dev libtool zip unzip v4l-utils libssl-dev \
python3-pip cmake git iputils-ping net-tools dwarves \
guvcview python-is-python3 bc

Get the config and compile

$ cd /usr/src
$ TAGVERNUM=x.x.x.x
$ TAGVER=linux-msft-wsl-${TAGVERNUM}
$ sudo git clone \
-b ${TAGVER} \
https://github.com/microsoft/WSL2-Linux-Kernel.git \
${TAGVERNUM}-microsoft-standard \
&& cd ${TAGVERNUM}-microsoft-standard
$ sudo cp /proc/config.gz config.gz \
&& sudo gunzip config.gz \
&& sudo mv config .config
$ uname -r -v
5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024

$ sudo apt update && sudo apt upgrade -y
$ sudo apt install -y \
build-essential flex bison \
libgtk-3-dev libelf-dev libncurses-dev autoconf \
libudev-dev libtool zip unzip v4l-utils libssl-dev \
python3-pip cmake git iputils-ping net-tools dwarves \
guvcview python-is-python3 bc

$ cd /usr/src
$ TAGVERNUM=5.15.153.1 \
&& TAGVER=linux-msft-wsl-${TAGVERNUM} \
&& WINUSERNAME=<windows username>
$ sudo git clone --depth 1 -b ${TAGVER} \
https://github.com/microsoft/WSL2-Linux-Kernel.git \
${TAGVERNUM}-microsoft-standard \
&& cd ${TAGVERNUM}-microsoft-standard

Copy .config file from previous step
$ sudo make menuconfig


$ sudo make -j$(nproc) KCONFIG_CONFIG=.config \
&& sudo make modules_install -j$(nproc) \
&& sudo make install -j$(nproc)

$ sudo rm /mnt/c/Users/${WINUSERNAME}/vmlinux
$ sudo cp /usr/src/${TAGVERNUM}-microsoft-standard/vmlinux /mnt/c/Users/${WINUSERNAME}/

Check what is in your config /mnt/c/Users/${WINUSERNAME}/.wslconfig

$ cat << 'EOT' > /mnt/c/Users/${WINUSERNAME}/.wslconfig
[wsl2]
kernel=C:\\Users\\<windows username>\\vmlinux
EOT

Make sure you have configured support for USB camera in your configuration

Device Drivers:

  • Multimedia support:
  • [*] Multimedia support
  • [*] Cameras/video grabbers support
  • [*] Media USB Adapters
  • [*] USB Video Class (UVC)

Here is the important difference for usb camera

CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_SUPPORT_FILTER=y
CONFIG_MEDIA_SUBDRV_AUTOSELECT=y

#
# Media device types
#
CONFIG_MEDIA_CAMERA_SUPPORT=y
# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
# CONFIG_MEDIA_RADIO_SUPPORT is not set
# CONFIG_MEDIA_SDR_SUPPORT is not set
# CONFIG_MEDIA_PLATFORM_SUPPORT is not set
# CONFIG_MEDIA_TEST_SUPPORT is not set
# end of Media device types

CONFIG_VIDEO_DEV=y
CONFIG_MEDIA_CONTROLLER=y

#
# Video4Linux options
#
CONFIG_VIDEO_V4L2=y
CONFIG_VIDEO_V4L2_I2C=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_VIDEO_ADV_DEBUG is not set
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
# end of Video4Linux options

#
# Media controller options
#
# end of Media controller options

#
# Media drivers
#

#
# Drivers filtered as selected at 'Filter media drivers'
#
CONFIG_MEDIA_USB_SUPPORT=y

#
# Webcam devices
#
CONFIG_USB_VIDEO_CLASS=y
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_GSPCA is not set
# CONFIG_USB_PWC is not set
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set

In a windows terminal

C:\> wsl --update
Checking for updates...
Downloading update...
Installing update...
This change will take effect the next time you reboot WSL. To force a reboot, run 'wsl --shutdown'.
Kernel version: 5.10.102.1

C:\> wsl --shutdown

Now you should have your new kernel running

 uname -v -r
5.15.153.1-microsoft-standard-WSL2+ #1 SMP Thu Jul 11 15:13:57 CEST 2024

Note the + and #1 that indicates is the number of times the kernel was built

Now the video camera should be recognized by the kernel

[  179.992700] usb 1-1: new high-speed USB device number 2 using vhci_hcd
[ 180.142668] usb 1-1: SetAddress Request (2) to port 0
[ 180.192670] usb 1-1: New USB device found, idVendor=045e, idProduct=0779, bcdDevice= 1.06
[ 180.192675] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 180.192677] usb 1-1: Product: Microsoft® LifeCam HD-3000
[ 180.192678] usb 1-1: Manufacturer: Microsoft
[ 180.197494] usb 1-1: Found UVC 1.00 device Microsoft® LifeCam HD-3000 (045e:0779)
[ 180.210002] input: Microsoft® LifeCam HD-3000: Mi as /devices/platform/vhci_hcd.0/usb1/1-1/1-1:1.0/input/input0

$ ls /dev/video*
/dev/video0 /dev/video1

Troubleshooting video

sudo apt install v4l-util
v4l2-ctl -d /dev/video0 --all
guvcview

This guide was made possible by, https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf

Another usecase is to be able to mount loopback filesystems, such as QNX6, as described here in the linux kernel driver database, https://cateee.net/lkddb/web-lkddb/QNX6FS_FS.html#google_vignette

--

--