Friday, December 5, 2008

Hacked an old driver to work under new linux kernels

Yesterday, I had to purchase a "PCI to parallel port" multi-I/O card to get the Xilinx Parallel IV cable to work on the Dell machines in our Lab (these PCs did not come with a parallel port, only USBs).

The card was from EnterMultimedia based on WCH352 chip. I am currently on Ubuntu 8.10 with 2.6.27 kernel. But after connecting the card and rebooting, the card was not detected by Linux. Well, actually it did detect it, but as some serial device for which no driver was found, and I could not find any /dev/lp0 or /dev/parport0. So, I looked into the driver CD that came with it, and found a linux driver (I did not expect to find it though)!
Tried to install it, but it turned out to be trying to use lp.o and parport_pc.o modules, both for old 2.4 linux kernels. No wonder the modules were not found in my system (and would not load even if they were present). To make matters worse, the 'installer' (well, hardly an installer... seemed to me more like a program that acted as some kind of wrapper using lp and parport_pc kernel modules for their work) was a compiled binary file without any source code provided on the CD.

So, after some head scratching, I decided to open the binary file using vim, and searched for 'parport_pc.o' and 'lp.o'. Found it, and then replaced them with 'parport_pc.ko' and 'lp.ko' respectively. Tried to run the file again, and it promptly responded with a segmentation fault. I had definitely jumbled up the addresses of different instruction in the binary, which the linker had worked hard to setup.

Then I did two things. First, changed the binary file so that now, 'parport_pc.ko' became 'parprt_pc.ko' and 'lp.ko' became 'l.ko' so that their length became same as their original names in the binary. Second, made a copy of the corresponding modules in my system and renamed them to reflect the new names for the binary file to be able to load them. Then, I ran depmod (I don't think it was required though, but well, did not hurt anyway).

Now I ran the binary file again, and voila, new devices /dev/lp0, /dev/lp1, /dev/parport0 and /dev/parport1 (dunno how lp1 and parport1 appeared though) have now appeared in my system :-)