I want to work with a CH340 USB-to-serial adapter from within WSL.
I'm using usbipd-win to attach the USB device directly to WSL.
After plugging in the device, I expect a /dev/ttyUSB0 serial port/device to appear.
This doesn't happen because the needed kernel module ch341 isn't loaded.
If I load the module manually with sudo modprobe ch341, /dev/ttyUSB0 shows up as expected and I can successfully communicate through it.
I'm trying to get the kernel module to load automatically.
Additionally, I would prefer if /dev/ttyUSB0 is created with mode 660 and group dialout (or alternatively mode 666) instead of mode 600 with owner and group root.
I have a feeling this should be possible through udev.
Things I've found so far
The device has vendor ID 1a86 and product ID 7523.
Some people experience a similar issue where the culprit is a braille display brltty that uses the same vendor and product ID as the CH340 adapter. Solutions to this are uninstalling brltty or disabling /usr/lib/udev/rules.d/85-brltty.rules.
On my machine, this package is not installed and the rule does not exist.
From my reading (and extremely limited understanding), it seems that udev is responsible for loading the required kernel modules when the device is plugged in.
It seems like there are no rules on my machine that would trigger this (correctly).
With grep, I've found this rule in /etc/udev/rules.d/70-snap.snapd.rules:
# QinHeng Electronics HL-340
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ENV{ID_MM_DEVICE_MANUAL_SCAN_ONLY}="1"
as well as this entry in /usr/lib/udev/hwdb.d/20-usb-vendor-model.hwdb:
usb:v1A86p7523*
ID_MODEL_FROM_DATABASE=CH340 serial converter
Additional info
$ uname -r
6.6.87.2-microsoft-standard-WSL2
dmesg output upon connecting the device without the module loaded:
$ dmseg
[ 3803.225441] vhci_hcd vhci_hcd.0: pdev(0) rhport(0) sockfd(3)
[ 3803.225738] vhci_hcd vhci_hcd.0: devid(393219) speed(2) speed_str(full-speed)
[ 3803.226107] vhci_hcd vhci_hcd.0: Device attached
[ 3803.401793] vhci_hcd: vhci_device speed not set
[ 3803.461864] usb 1-1: new full-speed USB device number 6 using vhci_hcd
[ 3803.537795] vhci_hcd: vhci_device speed not set
[ 3803.597795] usb 1-1: SetAddress Request (6) to port 0
$ modinfo ch341
filename: /lib/modules/6.6.87.2-microsoft-standard-WSL2/kernel/drivers/usb/serial/ch341.ko
license: GPL v2
alias: usb:v9986p7523d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v4348p5523d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v2184p0057d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v1A86p7523d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v1A86p7522d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v1A86p5523d*dc*dsc*dp*ic*isc*ip*in*
depends: usbserial,usbcore
retpoline: Y
intree: Y
name: ch341
vermagic: 6.6.87.2-microsoft-standard-WSL2 SMP preempt mod_unload modversions
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 1a86:7523 QinHeng Electronics CH340 serial converter
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ cat /sys/devices/platform/vhci_hcd.0/usb1/1-1/1-1:1.0/modalias
usb:v1A86p7523d0264dcFFdsc00dp00icFFisc01ip02in00
What follows is the output of udevadm info --attribute-walk --name=/dev/ttyUSB0 with the module loaded. When the module is not loaded, the output of udevadm info --attribute-walk --path=/devices/platform/vhci_hcd.0/usb1/1-1/1-1:1.0 is essentially the same but without the first two levels and the 3rd level having DRIVER=="" instead of DRIVERS=="ch341".
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/platform/vhci_hcd.0/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
DRIVER==""
ATTR{power/control}=="auto"
ATTR{power/runtime_active_time}=="0"
ATTR{power/runtime_status}=="unsupported"
ATTR{power/runtime_suspended_time}=="0"
looking at parent device '/devices/platform/vhci_hcd.0/usb1/1-1/1-1:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ch341-uart"
ATTRS{port_number}=="0"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"
looking at parent device '/devices/platform/vhci_hcd.0/usb1/1-1/1-1:1.0':
KERNELS=="1-1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="ch341"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="02"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bNumEndpoints}=="03"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/platform/vhci_hcd.0/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ff"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="98mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0264"
ATTRS{bmAttributes}=="80"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="6"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="7523"
ATTRS{idVendor}=="1a86"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="0"
ATTRS{power/active_duration}=="2571684"
ATTRS{power/autosuspend}=="2"
ATTRS{power/autosuspend_delay_ms}=="2000"
ATTRS{power/connected_duration}=="2571684"
ATTRS{power/control}=="on"
ATTRS{power/level}=="on"
ATTRS{power/persist}=="1"
ATTRS{power/runtime_active_time}=="2571390"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{product}=="USB Serial"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="12"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="14"
ATTRS{version}==" 1.10"
looking at parent device '/devices/platform/vhci_hcd.0/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0606"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 6.6.87.2-microsoft-standard-WSL2 vhci_hcd"
ATTRS{maxchild}=="8"
ATTRS{power/active_duration}=="6219812"
ATTRS{power/autosuspend}=="0"
ATTRS{power/autosuspend_delay_ms}=="0"
ATTRS{power/connected_duration}=="6345232"
ATTRS{power/control}=="auto"
ATTRS{power/level}=="auto"
ATTRS{power/runtime_active_time}=="6219803"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="125428"
ATTRS{power/wakeup}=="disabled"
ATTRS{power/wakeup_abort_count}==""
ATTRS{power/wakeup_active}==""
ATTRS{power/wakeup_active_count}==""
ATTRS{power/wakeup_count}==""
ATTRS{power/wakeup_expire_count}==""
ATTRS{power/wakeup_last_time_ms}==""
ATTRS{power/wakeup_max_time_ms}==""
ATTRS{power/wakeup_total_time_ms}==""
ATTRS{product}=="USB/IP Virtual Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{rx_lanes}=="1"
ATTRS{serial}=="vhci_hcd.0"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="172"
ATTRS{version}==" 2.00"
looking at parent device '/devices/platform/vhci_hcd.0':
KERNELS=="vhci_hcd.0"
SUBSYSTEMS=="platform"
DRIVERS=="vhci_hcd"
ATTRS{driver_override}=="(null)"
ATTRS{nports}=="16"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{usbip_debug}=="0"
looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"