When I bought UNI-T UT61E digital multimeter, I planned to to use the open source tool Sigrok to capture voltage, current or resistance data with my Ubuntu 14.04 machine. Unfortunately, it was just not working for me and I kept getting some “Invalid function byte” error messages, so I asked on Sigrok mailing list, and since it worked for others, I was in big troubles. It turned out the RS-232 to USB dongle I used:
1 2 |
idVendor 0x1a86 QinHeng Electronics idProduct 0x7523 HL-340 USB-Serial adapter |
was most likely to culprit, so I decided to buy another random USB to serial dongle on eBay, and after a few weeks I received it only to find out it had the exact same VID:PID, so I was out of luck. Finally, I gave up on Sigrok on Linux, and tested the power consumption of some Rockchip RK3288 & Amlogic S802 devices in a Windows 7 virtual machine running in my Ubuntu 14.04 host PC. A few days later, Karl Parsonn left a comment saying ch341 driver just ignored parity (UNI-T DMM use odd parity), but that he wrote a patch that should eventually make it to mainline.
Since I did not want to wait I decided to build ch341.ko with the patched driver, and I can now use Sigrok with my HL-340 USB-Serial adapter successfully, but I’ll write more about that in another post, and today, I’ll document the steps I followed to build the driver for my machine.
Instructions to build a kernel module in Ubuntu are already available, but the patch for ch341 driver is for Linux 3.18.6, and Ubuntu 14.04 comes with Linux 3.13. So I had two choices:
- Backport the driver to Linux 3.13
- Upgrade my Ubuntu kernel to 3.18
I decided to go with option 1 at first, but I quickly changed my mind as there’s been a bit too many modifications between the two versions, and it started to be time consuming. So it was time for plan B, or rather option 2. I could probably have use the Karl’s Linux kernel, but I remembered having read that Canonical makes some changes to the Linux kernel, so instead I went to http://kernel.ubuntu.com/~kernel-ppa/mainline/ to download and install Linux 3.18 in my machine (This is 3.18.0, but with hindsights I should have gone with 3.18.6 instead, but it still worked):
1 2 3 4 5 |
cd /tmp/ wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.18-vivid/linux-headers-3.18.0-031800-generic_3.18.0-031800.201412071935_amd64.deb wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.18-vivid/linux-headers-3.18.0-031800_3.18.0-031800.201412071935_all.deb wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.18-vivid/linux-image-3.18.0-031800-generic_3.18.0-031800.201412071935_amd64.deb sudo dpkg -i linux-headers-3.18.0-*.deb linux-image-3.18.0-*.deb |
This steps requires a reboot. In case it does not boot at all, you should be able to boot one of the older Linux kernel via grub, and remove the new mainline kernel, so I believe this step is relatively safe.
Then I checkout the Linux kernel and downloaded and applied Ubuntu specific patchsets:
1 2 3 4 5 6 7 8 9 10 11 |
mkdir workddir cd workdir git clone git://kernel.ubuntu.com/virgin/linux-stable.git v3.18 wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.18-vivid/0001-base-packaging.patch wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.18-vivid/0002-debian-changelog.patch wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.18-vivid/0003-configs-based-on-Ubuntu-3.18.0-6.7.patch cd v3.18 git checkout v3.18 patch -p2 < ../0001-base-packaging.patch patch -p2 < ../0002-debian-changelog.patch patch -p2 < ../0003-configs-based-on-Ubuntu-3.18.0-6.7.patch |
Backup the current driver:
1 |
sudo mv -v /lib/modules/$(uname -r)/kernel/drivers/usb/serial/ch341.ko /lib/modules/$(uname -r)/kernel/drivers/usb/serial/ch341.ko_backup |
Then I mostly followed the build instructions found on Askubuntu to setup the kernel to build modules:
1 2 3 4 |
make oldconfig make prepare make scripts cp -v /usr/src/linux-headers-3.18.0-031800-generic/Module.symvers . |
and update the code with the new driver, build and install the module:
1 2 3 4 |
cd drivers/usb/serial/ wget https://raw.githubusercontent.com/karlp/linux/ch341-3.18.6/drivers/usb/serial/ch341.c make -C /lib/modules/$(uname -r)/build M=$(pwd) modules sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install |
Finally run depmod, unload the old module if needed, and load the newly built module.
1 2 3 |
sudo depmod sudo modprobe -r ch341 sudo modprobe -v ch341 |
Done. I’ve now got a CH341 driver that supports no parity or odd/even parities.
Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
I would really like to learn how to do this for my android boxes/sticks. Good stuff
@Karl Johnson
It will be somewhat similar, but you need to find the source code for your box.
I reproduced instructions one reader gave me to build a JoyStick driver for Android -> http://www.cnx-software.com/2012/09/11/building-kernel-modules-for-allwinner-a10-devices-android/
This bug should fixed upstream. Actually I am reversing some chinese windows software in order to toggle gpios on ch341. There are plenty of bios flashers on aliexpress for some 3eur or so based on that chip, wheremost of the gpios are used. See also my page here:
http://www.zoobab.com/ch341-usb-spi-i2c-uart-isp-dongle
Thanks for the patch Zoobab + thanks for the post cnxsoft!
This tool might be also of any help for Ubuntu/debian kernel modules:
https://wiki.debian.org/ModuleAssistant
http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-5/src/sys/dev/usb/uchcom.c
“driver for WinChipHead CH341/340, the worst USB-serial chip in the world.”