Archive for February, 2009

Kerneldriver for LCD display (Tyan M1000 display for GT14 barebone)

So we bought this 1U Tyan GT14 Barebone with a LCD display and buttons in front of it. It was chosen mainly because of it’s anonymity and the LCD display.

So I set to download LCD drivers for linux. First I couldn’t find them at all.. The page at tyan.com is extremely slow, and even with google cache, it was not possible to find the driver. After a while, I tried connecting to their FTP server, where I were more lucky. Here I found a C example of how to write text to the display. Only problem was, it was linked to a binary library which was compiled with a different libc version. Shit out of luck I thought, no. I searched the FTP a bit more, and suddenly I found a lcdproc module by the Tyan staff. And it included all the source!

Yippee! But I don’t like the way LCDproc prevents me from doing what I want. I want to be able to control it directly, but from several sources. So I went to create a kernel module for Linux. Partly also because I wanted to play a bit with kernel development again :P

So attached you can find the source code for the new M1000 tyanlcd driver for 2.6 kernels.
tyanlcd-0.1.tar.gz

It actually took me a while longer to do. Not because of very big problems. But because as I started to google about on how to access the serial port from kernel-space, I quickly found out that it is not very easy. There is a lot of serial drivers, and even though this device will only be on tyan mainboards, so it sould be safe, I wanted to be sure it worked on any serial port that linux has support for. I tried looking at serio, but found ot that this was the wrong way to go. And then read Alan Cox mentioning somwhere that the best approach to use the serial port would be to create a new line discipline. But I could not find a good description of this, or even how to use it when done.

So I ended up using the not so loved filp_open() to open /dev/ttyS1 where the LCD device always resides in a tyan barebone. This way I had acces to the device using file->f_op->write() and someone used file->f_op->ioctl, but I found out that this was not exported in the file object I received. So I went on investigating the insides of the kernel myself, and finally found a way to reach it’s ioctl function. The tty object resides inside file->private_data, and inside the tty object you have a driver struct, with a ops struct which have the ioctl function. So by doing:

1
2
  tty=(struct tty_struct*)f->private_data;
  tty->driver->ops->ioctl(tty, f, TCSETS, (unsigned long)&settings);

I was finally able to set the correct baud rate, number of bits, stop bits, etc. As soon as this was done, it was piece of cake writing text to the LCD display using the original lcdproc driver code as a template for the instructions to the device.

After this proof of concept worked, I added the posibility to both read and write to the display using the /proc filesystem. The driver creates a file called /proc/tyanlcd where you can send text which wil be sent directly to the display. The first 16 characters is the first line, and the next 16 characters is the last line. (the display is 16×2 characters).

Reading the proc file gives you both lines on a single line. Seperate them by 16 characters and you have the current two lines displayed on the display.

Next task will be to make support for the buttons.

Small videoclip of the date showing in the display: mov02074.avi
Which shows the realtime output of the following proof of concept bash script:

1
2
3
4
while true; do
  echo -n "    $(date +%H:%M:%S)      " > /proc/tyanlcd
  sleep 1
done