Rebuilding the USB serial driver to allow for DMX (250000) baud
I wanted to play with a new light and wanted to just use a standard USB serial device. In the past I'd just patched the driver, but that no longer appears possible. (This is a good thing, I was always surprised that used to be able to do this) This meant building the driver. This *should* be simple, but it wasn't. This outlines how to to rebuild the serial driver for Raspbian.The sequence for building the driver should be simple:
1. Get the source for the driver
2. Get the kernel headers
3. Create a simple Makefile
4. Build
5. Serve
I mainly ran into issues getting the correct headers.
Get the source for the driver
uname -r will tell you the version of the kernel:$ uname -r
4.9.35-v7+
Now you can pull in the source directly from github, updating the version number. Pull in the c file and the header:
wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-4.9.y/drivers/usb/serial/pl2303.c
wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-4.9.y/drivers/usb/serial/pl2303.h
Get the kernel headers (Raspbian)
apt install is used to pull in the kernel headers.
apt install raspberrypi-kernel-headers
For my installation, the headers getting pulled in didn't match the running kernel. The kernel version was actually quite far ahead. You should ensure that you're up-to-date first
apt-get update
apt-get upgrade
init 6
or in my case:
apt remove raspberrypi-kernel-headers
apt-get update
apt-get install --reinstall raspberrypi-bootloader raspberrypi-kernel
init 6
Once rebooted:
apt install raspberrypi-kernel-headers
Check that you have the correct headers. If you have the 'build' directory, then you should be good.
ls -l /lib/modules/$(uname -r)/build
Create the Makefile
I'm building pl2303.ko, so all my Makefile needs to contain is:obj-m := pl2303.o
Yes - that's all.
Build
With the headers in place and the Makefile in place, this is all you should have to do to build:make -C /lib/modules/$(uname -r)/build M=$PWD modules
Serve
You may need to remove the current module:rmmod pl2303
Now you can install your new module:
insmod pl2303.ko
250000 Baud
The reason for having to build a driver were to be able to set the Baud to 250000 for my DMX device. Linux still has preconceived notions about baud rate, and 250000 isn't one of them, so you'll not be able to easily set the speed you want. I have some existing code (dmx) that sets the baud rate to 500000 with the expectation that the driver will set it to the next closest speed. I used to patch the driver to make this closest (lower) speed to be 250000, but that doesn't work anymore.
if (baud == 500000) baud=250000;
I added the above line into the driver code - if the baud requested is 500000, then set the baud to 250000. To put this in context:
/*
* Use direct method for supported baud rates, otherwise use divisors.
*/
if (baud == 500000) baud=250000;
baud_sup = pl2303_get_supported_baud_rate(baud);
if (baud == baud_sup)
baud = pl2303_encode_baud_rate_direct(buf, baud);
else
baud = pl2303_encode_baud_rate_divisor(buf, baud);
This means that if 500k baud is selected it will change the request to 250k. The 'if ' section (baud_sup) will fail and the baud rate will be set using pl2303_encode_baud_rate_divisor.
That's all.
REF: https://raspberrypi.stackexchange.com/questions/63879/installed-kernel-headers-and-uname-r-differ
REF: https://www.youtube.com/watch?v=Zn8mEZXr6nE&list=PL2GL6HVUQAuksbptmKC7X4zruZlIl59is
REF: https://www.raspberrypi.org/documentation/raspbian/updating.md