LCDKuro

<> -- Add a Display and Keyboard to your Kurobox

An Entry For the 8/1-11/15 2006 Contest by russK

If you are wishing you could see what your Kurobox is doing without network access, or if you want another way to log in to your Kurobox, then this project might be for you.



Goals and Wishlist for LCDKuro
This project is to add an LCD display device to the kurobox. The display will be used to provide useful information and a handy console for logging in with a keyboard.

The goals I have set for this project are


 * Provide a small console with an LCD display and a keyboard that can be used for logging in and running command line commands
 * Provide machine status information on an LCD display with statistics like current time, CPU activity, CPU Load, memory usage, disk space usage, etc. Most of this information can be provided by an open-source package called LCDProc.  LCDKuro can rely heavily on LCDProc.
 * I would like to be able to provide multiple virtual consoles selected with alt-Fkey like on many typical linux distributions. This would ideally include switching between the console logins and the LCDProc functionality.
 * I would like to have the LEDs on the side of my chosen LCD device to provide some useful information, e.g. flashing for disk activity, mimic the kurobox's LEDs, blink when new mail arrives, blink when a new topic is posted to the kurobox forums, whatever.

Crystalfontz CFA635-TMF LCD Display
There are all sorts of LCDs of available from various manufacturors. I have chosen the Crystalfontz CFA635-TMF (CFA635TMFKU1) for this project. It's a 20x4 display with a USB interface, has good support in LCDProc, has some nifty buttons that might prove useful and most of all, it looks cool. It is designed to fit in a typical 5-1/4 half-height PC bay on the front panel of a PC case. I will install the display in a small box and set it on the desk next to the keyboard. I ordered one through the crystalfontz web site ... it includes a USB cable with the proper connector. The total cost of $81.50 includes $9.00 for shipping. This seems a bit high, but considering the cool factor of the envisioned product, I can live with it.



USB Keyboard
I already own a USB keyboard I am going to use for this project - if you don't have one, I think they can be had for around $10.

LCDProc [[Image:Lcdproc now.gif]]
LCDProc is an open-source package for controlling LCD displays under Linux. LCDProc has a server component for controlling the display, while clients can connect to the server and provide data to be displayed. Many different types of displays are supported by LCDProc. The different displays are supported by LCDProc through drivers. Only the server needs to worry about the details of the drivers and display types, while the client can remain somewhat unaware of the details. This makes it easy to change display types and leaving the client code very much intact.
 * LCDProc

The latest released version of LCDProc is 0.5.0 as of 4/15/2006. I use gentoo on my kurobox, and the latest version of LCDProc available in portage is 0.4.5 which is 2 years old. Around 9/9/06 I found I could not get LCDproc 0.5.0 up and running. It did work on my AMD64 box. I captured the output of the serial packet driver example program with usbmon and I saw byte-swapping issues. After looking at the code, it was fairly simple to fix, the only issue was a CRC word in the packet protocol. I fixed my copy and sent a patch to the LCDProc mailing list. The developers of LCDProc fixed their CVS version the same day and asked me to try their nightly build. Their nightly build is on sourceforge. Now that's what is so awesome about opensource software! I am using the CVS nightly build lcdproc-CVS-current-20060923 for LCDKuro.


 * Virtual Console

Someone has created a virtual console driver for LCDProc - this will come in handy for logging into the LCD device and running command-line commands. The virtual console client for LCDProc is called lcdvc. The nightly build also fixes a bug in lcdvc, so that's another good reason for using the nightly build.

There is some talk about LCDProc 0.5.1 coming out soon. If LCDProc 0.5.1 (or better) is out as you read this, you may want to use the stable release instead of the nightly build.

Kernel Support for LCDKuro
There are several kernel modules I had to build for LCDKuro. You can either follow along here to build your own modules, or you can download a prebuilt kernel and modules that Sylver has built. You can download Sylver's kernel and modules here: Sylver's 2.6.18 kernel + modules. Also see the end of this wiki in the Closing for the necessary .config settings.

Using a keyboard on the kurobox requires support in the kernel. This support is not provided in the regular kurobox kernels, so a custom kernel will have to be built or possibly just a module.

At the start of the project, I discovered my kernel does not have USB Keyboard support. In my .config file I had: # # USB HID Boot Protocol drivers # # CONFIG_USB_KBD is not set

I am using Sylver's 2.6.17.1 uImage kernel I so I prepared the kernel source per his instructions he graciously provided in the kurobox forums. This is what I did to create a new kernel and keyboard modules:


 * 1) cd /usr/src
 * 2) wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.1.tar.bz2
 * 3) wget http://genbako.vodapone.com/kurobox-sources-2.6.17.patch
 * 4) wget http://www.holtmann.org/linux/kernel/patch-2.6.17-mh1.gz
 * 5) tar xjf linux-2.6.17.1.tar.bz2
 * 6) cd linux-2.6.17.1
 * 7) patch -Np1 < ../kurobox-sources-2.6.17.patch
 * 8) gzcat ../patch-2.6.17-mh1.gz | patch -Np1
 * 9) vi (or nano) Makefile # add -mh1 to EXTRAVERSION = .1, result: EXTRAVERSION = .1-mh1
 * 10) cp /boot/.config .config
 * 11) export ARCH=ppc
 * 12) make oldconfig # this step may be uneccessary but I did it anyway
 * 13) make menuconfig
 * 14) select Device Drivers -> USB support
 * 15) # navigate down to USB Human Interface Device (full HID) support
 * 16) # press 'M' to select support as a kernel module
 * 17) # Exit
 * 18) # Exit
 * 19) # Device Drivers -> Input Device Support
 * 20) # navigate down to Event Interface
 * 21) # press 'M' to select support as a kernel modules
 * 22) # Exit
 * 23) # Exit
 * 24) # Exit  Yes (Save configuration)
 * 25) make vmlinux && make modules && make modules_install

Also, to be sure since I didn't know which compiler Sylver used to build the kernel, I re-built my uImage kernel like this (I use Nijino's uboot):


 * 1) wget http://www.kurobox.com/sylver/u-boot/mkimage
 * 2) chmod 0755 mkimage
 * 3) mv mkimage /usr/bin/
 * 4) make uImage
 * 5) mv /boot/uImage /boot/uImage.bak
 * 6) cp arch/ppc/boot/images/uImage /boot/
 * 7) mv /boot/System.map /boot/System.map.bak
 * 8) mv /boot/.config /boot/.config.bak
 * 9) cp System.map /boot
 * 10) cp .config /boot

The newly built usb module is usbhid. With the new module in place in /lib/modules/kernel/2.6.17.1-mh1_kuro-box (from make modules_install), the driver can be checked with the following command:

usb 2-1: new low speed USB device using ohci_hcd and address 3 usb 2-1: configuration #1 chosen from 1 choice input: Logitech USB Receiver as /class/input/input2 input: USB HID v1.10 Keyboard [Logitech USB Receiver] on usb-0000:00:0e.0-1 input: Logitech USB Receiver as /class/input/input3 input: USB HID v1.10 Mouse [Logitech USB Receiver] on usb-0000:00:0e.0-1 total 0 crw-rw 1 root root 13, 33 Sep 13 20:58 mouse1 crw-rw 1 root root 13, 2 Sep 13 20:58 js2 crw-rw 1 root root 13, 1 Sep 13 20:58 js1 crw-rw 1 root root 13, 0 Sep 13 20:58 js0 crw-rw 1 root root 13, 35 Sep 13 20:58 mouse3 crw-rw 1 root root 13, 34 Sep 13 20:58 mouse2 crw-r--r-- 1 root root 13, 63 Sep 13 20:58 mice crw-rw 1 root root 13, 3 Sep 13 20:58 js3 crw-r--r-- 1 root root 13, 32 Sep 14 20:42 mouse0 crw--- 1 root root 13, 65 Sep 14 20:42 event1 crw--- 1 root root 13, 64 Sep 14 20:42 event0
 * 1) modprobe usbhid
 * 2) modprobe evdev
 * 3) # now plug in your keyboard
 * 4) dmesg
 * 1) ls -ltr /dev/input

My dmesg is now showing a keyboard and a mouse (I'm using a wireless logitec combo, I won't be using the mouse for this project). And, I have event0 in /dev/input. Now check to see if the keyboard is working ...

0000000  E  \f   <   _  \0 002 350 235  \0 001  \0   %  \0  \0  \0 001 0000020  E  \f   <   _  \0 002 350 245  \0  \0  \0  \0  \0  \0  \0  \0 0000040  E  \f   <   _  \0 004 334   u  \0 001  \0   %  \0  \0  \0  \0 0000060  E  \f   <   _  \0 004 334   }  \0  \0  \0  \0  \0  \0  \0  \0 0000100  E  \f   <   _  \0 005   x 263  \0 001  \0   $  \0  \0  \0 001 0000120  E  \f   <   _  \0 005   x 273  \0  \0  \0  \0  \0  \0  \0  \0 0000140  E  \f   <   _  \0 006   4   #  \0 001  \0   $  \0  \0  \0  \0 0000160  E  \f   <   _  \0 006   4   *  \0  \0  \0  \0  \0  \0  \0  \0 0000200  E  \f   <   _  \0 006 320   ]  \0 001  \0   %  \0  \0  \0 001 0000220  E  \f   <   _  \0 006 320   e  \0  \0  \0  \0  \0  \0  \0  \0 #
 * 1) od -c /dev/input/event0 # and press some keys

Kernel support for the Display
The day the display arrived. Wow, it looks great. I connected the display to my kurobox with the provided USB cable. Output in dmesg:

usb 2-1: new full speed USB device using ohci_hcd and address 5 usb 2-1: configuration #1 chosen from 1 choice

That's it. I did not expect more than that. It lit up and looked just like the picture above. Next step is to get LCDProc talking to the display.

The display also requires support in the kernel. The display uses a USB->Serial converter chip from FTDI. The driver is ftdi_sio. To get support from the kernel, a module can be built. Back to /usr/src/linux-/:

usbcore: registered new driver usbserial drivers/usb/serial/usb-serial.c: USB Serial Driver core drivers/usb/serial/usb-serial.c: USB Serial support registered for FTDI USB Serial Device usbcore: registered new driver ftdi_sio drivers/usb/serial/ftdi_sio.c: v1.4.3:USB FTDI Serial Converters Driver
 * 1) export ARCH=ppc
 * 2) make menuconfig
 * 3) Select Device Drivers -> USB Support ->
 * 4) USB Serial Converter support -> "M"
 * 5)  -> USB FTDI Single Port Serial Driver (EXPERIMENTAL) (NEW). -> "M"
 * 6)   ... Exit Exit Exit Exit Exit Yes
 * 7) make modules && make modules_install
 * 8) modprobe ftdi_sio
 * 9) dmesg

Now plugging in the display again ... dmesg:

usb 2-1: new full speed USB device using ohci_hcd and address 6 usb 2-1: configuration #1 chosen from 1 choice ftdi_sio 2-1:1.0: FTDI USB Serial Device converter detected drivers/usb/serial/ftdi_sio.c: Detected FT8U232AM usb 2-1: FTDI USB Serial Device converter now attached to ttyUSB0

There's the magic ... "converter now attached to ttyUSB0". I now have these in my /dev directory:

lrwxrwxrwx 1 root root 10 Sep 7 22:53 /dev/tts/USB0 -> ../ttyUSB0 crw-rw 1 root tty 188, 0 Sep 7 22:53 /dev/ttyUSB0
 * 1) ls -l /dev/tts/USB0
 * 1) ls -l /dev/ttyUSB0

Time to add myself to the tty group. I use vigr to edit the group file and add myself to the tty group. This might help avoid permission problems later when using the device:

tty:x:5:russ

Configuring LCDProc
LCDd and lcdproc use configuration files LCDd.conf and lcdproc.conf respectively. Here is the way to configure them for LCDKuro:

The LCDProc nightly build installs configuration files in /usr/local/etc. These are the critical lines in LCDd.conf for LCDKuro:
 * LCDd.conf

Driver=CFontzPacket ... DriverPath=/usr/local/lib/lcdproc/
 * 1) Driver=curses


 * lcdproc.conf

Use lcdproc.conf unmodified from the version supplied in the nightly build.


 * Making it start at bootup

I noticed that someone released a gentoo ebuild for LCDPRoc on 9/22/06. I am not too proud to borrow their init script. I copied it from /var/portage/app-misc/lcdproc/files/0.5.0-LCDd to /etc/init.d/LCDd and modified it to run the binary in /usr/local/sbin.

--background --exec /usr/local/sbin/LCDd -- -s 1 -f \ -c /usr/local/etc/LCDd.conf \ || ( eerror "Failed to start LCDd. Did you remember to set a driver in /usr/local/etc/LCDd.conf? See syslog for details." \                                                                     && return 1 )
 * 1) cp /var/portage/app-misc/lcdproc/files/0.5.0-LCDd /etc/init.d/LCDd
 * 2) vi /etc/init.d/LCDd
 * 3) # fixup to run from /usr/local/sbin add -c /usr/local/etc/LCDd.conf, and remove "1" from -f argument:
 * 4) # start-stop-daemon --start --quiet -m --pidfile /var/run/LCDd.pid \
 * 1) chmod +x /etc/init.d/LCDd
 * 2) /etc/init.d/LCDd start
 * 3) rc-update add LCDd default

Setting up Virtual Consoles for lcdvc
I have learned that linux virtual consoles have associated devices /dev/vcs and /dev/vcsa. See "man vcs". My kurobox running gentoo had only /dev/vcs and /dev/vcsa. My reference desktop running gentoo also has /dev/vcs1, vcs2, vcs3, ... and /dev/vcsa1, etc. I had a look at the /usr/sbin/MAKEDEV script and ran "MAKEDEV console" (covering my eyes). After the dust settled, I had 64 /dev/vcs devices and 64 /dev/vcsa devices. That ought to cover me for LCDKuro!

Afterwards, I ran these commands to fix up permissions:


 * cd /dev
 * chmod g+rw vcs*
 * chmod g+rw tty*
 * chmod g+rw console

LCDProc virtual console client "lcdvc"
Someone has written a virtual console client. This client is perfect for LCDKuro.

Initially, I had problems with lcdvc. I discovered I needed a patch (with my compiler (gcc 4.1.1) on the kurobox) to handle the fact that apparently a 'char' variable is implicitly unsigned. This problem is fixed in the nightly build of LCDProc.


 * Setting up agetty

I had to uncomment a getty line in my inittab. I am only using one virtual console even though I wanted multiple vc's in my initial goals. I had trouble getting multiple vc's to work. The line in /etc/inittab looks like this:

c1:12345:respawn:/sbin/agetty 38400 tty0 linux


 * Starting lcdvc at bootup

I borrowed heavily from the LCDd init script and created this one:


 * 1) vi /etc/init.d/lcdvc

depend { use LCDd } start { ebegin "Starting lcdvc" start-stop-daemon --start --quiet -m --pidfile /var/run/lcdvc.pid \ --background --exec /usr/local/bin/lcdvc \ || ( eerror "Failed to start lcdvc." \                        && return 1 ) sleep 1 eend $? } stop { ebegin "Stopping lcdvc" start-stop-daemon --stop --quiet --pidfile /var/run/lcdvc.pid eend $? }
 * 1) !/sbin/runscript
 * 2) Copyright 1999-2006 Gentoo Foundation
 * 3) Distributed under the terms of the GNU General Public License v2

Hard Disk Activity LED
I wanted to use the LEDs on the side of my LCD module to display something useful. LCDKuro adds a nifty Hard Disk Activity indicator.

LCDProc already provides the ability to turn the LEDs on and off. All that is needed is some code to monitor for hard disk activity and turn the LED on and off as appropriate. I wrote some code to do this job. The code is available here: diskMon.tar.gz. The code depends on a socket wrapper library called SocketW available here: SocketW.

I installed the binary executable in /usr/local/bin and created an init script like the others:

depend { use LCDd } start { ebegin "Starting diskMon" start-stop-daemon --start --quiet -m --pidfile /var/run/diskMon.pid \ --background --exec /usr/local/bin/diskMon \ || ( eerror "Failed to start diskMon." \                        && return 1 ) sleep 1 eend $? } stop { ebegin "Stopping diskMon" start-stop-daemon --stop --quiet --pidfile /var/run/diskMon.pid eend $? }
 * 1) !/sbin/runscript
 * 2) Copyright 1999-2006 Gentoo Foundation
 * 3) Distributed under the terms of the GNU General Public License v2


 * 1) /etc/init.d/diskMon start
 * 2) rc-update add diskMon default

lcdproc Standard Client
I created another initscript for lcdproc (the standard LCDProc client) just like the others above. I added them to the default runlevel too:


 * 1) /etc/init.d/lcdproc start
 * 2) rc-update add lcdproc default

Pictures
It is difficult getting quality pictures of the display. These are the best I have so far:


 * Miscellaneous Commands on Console




 * CPU Load




 * LED Lit for HDD Activity




 * Kurobox login



Remarks
LCDKuro is a great success. The goals are almost completely met:
 * Small console - Complete
 * LCDProc functionality - Complete
 * Multiple Virtual Consoles - not quite (one console works fine)
 * LED Usage - Complete

At first, when I started the project and I found that LCDProc did not work, I was very discouraged. I thought it would be difficult to debug and get everything working in time for submission in the contest. I compared the two machines I had and posted a message to the linux-usb mailing list. I was afraid the problem was in the USB driver. Fortunately somebody responded to my post and told me the problem was probably not in the USB driver but in the user code. So from there it did not take very long to determine that the LCD driver was not transmitting a CRC word to the display in the correct byte order that the display was expecting. Once that was fixed, the display worked perfectly. The developer of the LCDProc package quickly responded and put the fix in the nightly build.

I also had some troubles getting my USB keyboard to work at first. Again, I posted a message to the gentoo forums and someone replied with just enough of a clue to help me get it going.

I am completely blown away at how the open source community works with so many people helping out. It is an incredible phenomenom.

Summary of kernel drivers in .config
The following items necessary for the project are in my .config:

CONFIG_INPUT_EVDEV=m CONFIG_INPUT_KEYBOARD=y CONFIG_USB_KBD=m CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_FTDI_SIO=m