ЖКИ в OpenWrt

Вспомнился мой дипломный проект, блин, как же давно это было... Казалось таким сложным заданием написать в AVR Studio на ассемблере код для atmega8. И сколько было счастья, когда вывел на индикатор легендарный «HelloWorld!». А давайте посмотрим, сколько теперь нужно приложить усилий, чтобы решить аналогичную задачу. Попробуем подключить двух-строчный жк-индикатор к нашему роутеру.

Мне понравился проект LCD2USB — подключение ЖК-индикатора к компьютеру через USB (http://www.harbaum.org/till/lcd2usb/index.shtml). Удивительно простая аппаратная реализация и доступность прошивки. Тем более для LCD2USB в линуксе есть поддержка со стороны LCD4Linux (http://ssl.bulix.org/projects/lcd4linux/) - небольшая утилита, получающая информацию от ядра, приложений и отображающая ее на внешнем жк-дисплее.

Пропустим этап изготовления макетки и начнем вот отсюда. Итак, платка готова — оживим её.

На этапе конфигурации OpenWrt нужно отметить следующие модули:
Utilities:
<M> lcd4linux
<*> LCD2USB
Base system:
<*> busybox:
Linux System Utilities:
<*> lsusb

Также соберем тестовую программку из директории lcd2usb/testapp. Нужно прописать в makefile кросс-компилятор и соответствующие пути. Для этого добавим в makefile следующие строки:

CC = [..]staging_dir/toolchain-mipsel_gcc-4.3.3+cs_uClibc-0.9.31/bin/mipsel-openwrt-linux-gcc
INCLUDE_PATH = [..]staging_dir/target-mipsel_uClibc-0.9.31/usr/include
LIB_PATH = [..]/staging_dir/target-mipsel_uClibc-0.9.31/usr/lib

$(APP): $(APP).c
$(CC) -Wall -I$(INCLUDE_PATH) -L$(LIB_PATH) -o $@ $(APP).c -lusb

В итоге получится программка под названием lcd2usb. Скопируем её в /home/testapp/.

Устанавливаем пакеты:

root@OpenWrt:/# opkg install lcd4linux
Installing lcd4linux (r1116-2) to root...
Downloading ftp://ftp:ftp@192.168.0.9/lcd4linux_r1116-2_brcm47xx.ipk.
Installing libusb (0.1.12-2) to root...
Downloading ftp://ftp:ftp@192.168.0.9/libusb_0.1.12-2_brcm47xx.ipk.
Configuring libusb.
Configuring lcd4linux.

Подключаем индикатор. На экране индикатора должна быть надпись LCD2USB V1.09. Выглядеть примерно должно вот так:

Проверим, как отреагировал Linux на новое устройство. Смотрим вывод dmesg:

root@OpenWrt:/# dmesg
usb 1-1.4: new low speed USB device using ohci_hcd and address 4

Также смотрим вывод lsusb:

root@OpenWrt:/# lsusb
Bus 001 Device 001: ID 1d6b:0001
Bus 002 Device 001: ID 1d6b:0002
Bus 001 Device 002: ID 0a05:7211
Bus 001 Device 003: ID 0951:1603
Bus 001 Device 004: ID 0403:c630

Наличие в этом списке устройства с ID 0403:c630, говорит о том, что ядро распознало наш индикатор как устройство LCD2USB.

Запустим тестовую программку:


root@OpenWrt:/# /home/testapp/lcd2usb
-- LCD2USB test application --
-- (c) 2006 by Till Harbaum --
-- http://www.harbaum.org/till/lcd2usb --
Found LCD2USB device on bus 001 device 006.
Echo test successful!
Firmware version 1.9
Installed controllers: CTRL0
Keys: 0:off 1:off

На экране дисплея будет бегущая строка с текстом: «The quick brown fox jumps over the lazy dogs back ...»
Выглядеть примерно должно вот так:

Пробуем запустить lcd4linux в режиме отладки:

root@OpenWrt:/# lcd4linux -Fvv
LCD4Linux 0.11.0-SVN-1092 starting
Dump of /etc/lcd4linux.conf:
Display 'picoLCD'
Display:BA63.BarChar 219
Display:BA63.Driver 'WincorNixdorf'
Display:BA63.Model 'BA63'
Display:BA63.Port '/dev/tts/0'
Display:BA63.SelfTest 0
Display:BA63.Speed 9600
Display:BWCT.asc255bug 1
Display:BWCT.Contrast 220
Display:BWCT.Driver 'BWCT'
Display:BWCT.Icons 1
Display:BWCT.Size '20x4'
Display:CF631.Backlight 50
Display:CF631.Contrast 95
Display:CF631.Driver 'Crystalfontz'
Display:CF631.Icons 1
Display:CF631.Model '631'
Display:CF631.Port '/dev/tts/USB0'
Display:CF631.Speed 115200
Display:CF632.Driver 'Crystalfontz'
Display:CF632.Icons 1
Display:CF632.Model '632'
Display:CF632.Port '/dev/tts/0'
Display:CF632.Speed 19200
Display:CF633.Backlight 50
Display:CF633.Contrast 16
Display:CF633.Driver 'Crystalfontz'
Display:CF633.Icons 1
Display:CF633.Model '633'
Display:CF633.Port '/dev/tts/0'
Display:CF633.Speed 19200
Display:CF635.Backlight 128
Display:CF635.Contrast 100
Display:CF635.Driver 'Crystalfontz'
Display:CF635.Icons 1
Display:CF635.Model '635'
Display:CF635.Port '/dev/ttyUSB0'
Display:CF635.Speed 115200
Display:CT20x4.Driver 'Beckmann+Egle'
Display:CT20x4.Icons 1
Display:CT20x4.Model 'CT20x4'
Display:CT20x4.Port '/dev/tts/0'
Display:ctinclud.Driver 'serdisplib'
Display:ctinclud.Inverted 0
Display:ctinclud.Model 'CTINCLUD'
Display:ctinclud.Options ''
Display:ctinclud.Port 'USB:7c0/1501'
Display:Curses.Driver 'Curses'
Display:Curses.Size '20x6'
Display:CW12232.Brightness 2
Display:CW12232.Driver 'Cwlinux'
Display:CW12232.Icons 1
Display:CW12232.Model 'CW12232'
Display:CW12232.Port '/dev/usb/tts/0'
Display:CW12232.Speed 19200
Display:G15.Contrast 10
Display:G15.Driver 'G-15'
Display:G15.Font '6x8'
Display:G15.Inverted 0
Display:G15.SingleKeyPress 1
Display:G15.UInput '/dev/input/uinput'
Display:HD44780-4bit.asc255bug 0
Display:HD44780-4bit.Bits 4
Display:HD44780-4bit.Driver 'HD44780'
Display:HD44780-4bit.Model 'generic'
Display:HD44780-4bit.Port '/dev/parports/0'
Display:HD44780-4bit.Size '16x1'
Display:HD44780-4bit.UseBusy 0
Display:HD44780-4bit.Wire.ENABLE 'DB6'
Display:HD44780-4bit.Wire.GPO 'GND'
Display:HD44780-4bit.Wire.RS 'DB4'
Display:HD44780-4bit.Wire.RW 'GND'
Display:HD44780-generic.asc255bug 0
Display:HD44780-generic.Driver 'HD44780'
Display:HD44780-generic.GPOs 8
Display:HD44780-generic.Model 'generic'
Display:HD44780-generic.Port '/dev/parports/0'
Display:HD44780-generic.Size '8x2'
Display:HD44780-generic.Wire.ENABLE 'STROBE'
Display:HD44780-generic.Wire.ENABLE2 'GND'
Display:HD44780-generic.Wire.GPO 'INIT'
Display:HD44780-generic.Wire.POWER 'GND'
Display:HD44780-generic.Wire.RS 'AUTOFD'
Display:HD44780-generic.Wire.RW 'GND'
Display:HD44780-I2C.asc255bug 0
Display:HD44780-I2C.Bits '4'
Display:HD44780-I2C.Bus 'i2c'
Display:HD44780-I2C.Device '70'
Display:HD44780-I2C.Driver 'HD44780'
Display:HD44780-I2C.Icons 1
Display:HD44780-I2C.Model 'generic'
Display:HD44780-I2C.Port '/dev/i2c-0'
Display:HD44780-I2C.Size '20x4'
Display:HD44780-I2C.Wire.ENABLE 'DB6'
Display:HD44780-I2C.Wire.GPO 'GND'
Display:HD44780-I2C.Wire.RS 'DB4'
Display:HD44780-I2C.Wire.RW 'DB5'
Display:HD44780-kernelconcepts.Driver 'HD44780'
Display:HD44780-kernelconcepts.Model 'HD66712'
Display:HD44780-kernelconcepts.Port '/dev/parports/0'
Display:HD44780-kernelconcepts.Size '20x4'
Display:HD44780-kernelconcepts.UseBusy 1
Display:HD44780-kernelconcepts.Wire.ENABLE 'STROBE'
Display:HD44780-kernelconcepts.Wire.ENABLE2 'GND'
Display:HD44780-kernelconcepts.Wire.GPO 'GND'
Display:HD44780-kernelconcepts.Wire.POWER 'GND'
Display:HD44780-kernelconcepts.Wire.RS 'INIT'
Display:HD44780-kernelconcepts.Wire.RW 'AUTOFD'
Display:HD44780-winamp.asc255bug 1
Display:HD44780-winamp.Driver 'HD44780'
Display:HD44780-winamp.Model 'generic'
Display:HD44780-winamp.Port '/dev/parports/0'
Display:HD44780-winamp.Size '20x4'
Display:HD44780-winamp.Timing.AH 20
Display:HD44780-winamp.Timing.AS 140
Display:HD44780-winamp.Timing.CLEAR 2250
Display:HD44780-winamp.Timing.CY 1000
Display:HD44780-winamp.Timing.EXEC 80
Display:HD44780-winamp.Timing.fuzz 100
Display:HD44780-winamp.Timing.GPO_PW 230
Display:HD44780-winamp.Timing.GPO_ST 20
Display:HD44780-winamp.Timing.HOME 2250
Display:HD44780-winamp.Timing.INIT1 4100
Display:HD44780-winamp.Timing.INIT2 100
Display:HD44780-winamp.Timing.ONOFF 2250
Display:HD44780-winamp.Timing.POWER 500
Display:HD44780-winamp.Timing.PW 450
Display:HD44780-winamp.Timing.WRCG 120
Display:HD44780-winamp.UseBusy 1
Display:HD44780-winamp.Wire.ENABLE 'STROBE'
Display:HD44780-winamp.Wire.ENABLE2 'GND'
Display:HD44780-winamp.Wire.GPO 'GND'
Display:HD44780-winamp.Wire.POWER 'GND'
Display:HD44780-winamp.Wire.RS 'INIT'
Display:HD44780-winamp.Wire.RW 'AUTOFD'
Display:Image.Background '00000022'
Display:Image.Basecolor '80d000'
Display:Image.Border 20
Display:Image.Driver 'Image'
Display:Image.Font '6x8'
Display:Image.Foreground '000000cc'
Display:Image.Format 'PNG'
Display:Image.Gap '-1x-1'
Display:Image.Pixel '4+1'
Display:Image.Size '120x32'
Display:LCD-Linux.Driver 'LCD-Linux'
Display:LCD-Linux.Size '20x2'
Display:LCD-Linux.UseBusy 0
Display:LCD2041.Contrast 160
Display:LCD2041.Driver 'MatrixOrbital'
Display:LCD2041.Model 'LCD2041'
Display:LCD2041.Port '/dev/tts/0'
Display:LCD2041.Speed 19200
Display:LCD2USB.Backlight 1
Display:LCD2USB.Driver 'LCD2USB'
Display:LCD2USB.Icons 1
Display:LCD2USB.Size '20x2'
Display:LCDTerm.Driver 'LCDTerm
Display:LCDTerm.Icons 1
Display:LCDTerm.Port '/dev/tts/0'
Display:LCDTerm.Size '20x4'
Display:LCDTerm.Speed 19200
Display:LCM-162.asc255bug 0
Display:LCM-162.Driver 'HD44780'
Display:LCM-162.Icons 1
Display:LCM-162.Model 'LCM-162'
Display:LCM-162.Port '/dev/parports/0'
Display:LCM-162.Size '16x2'
Display:LCM-162.UseBusy 1
Display:LK202.Contrast 256/2
Display:LK202.Driver 'MatrixOrbital'
Display:LK202.Model 'LK202-24-USB'
Display:LK202.Port '/dev/tts/USB0'
Display:LK202.Speed 19200
Display:LK204.Contrast 256/2
Display:LK204.Driver 'MatrixOrbital'
Display:LK204.Model 'LK204-24-USB'
Display:LK204.Port '/dev/usb/tts/0'
Display:LK204.Speed 19200
Display:LPH7508-serdisplib.Driver 'serdisplib'
Display:LPH7508-serdisplib.Model 'LPH7508'
Display:LPH7508-serdisplib.Port 'PAR:/dev/parports/0'
Display:LPH7508.Contrast 15
Display:LPH7508.Driver 'LPH7508'
Display:LPH7508.Font '6x8'
Display:LPH7508.Inverted 0
Display:LPH7508.Port '/dev/parports/0'
Display:M50530-24x8.Driver 'M50530'
Display:M50530-24x8.Duty 2
Display:M50530-24x8.Font '5x7'
Display:M50530-24x8.Port '/dev/parports/0'
Display:M50530-24x8.Size '24x8'
Display:M50530-24x8.Timing.fuzz 100
Display:M50530-24x8.UseBusy 1
Display:M50530-24x8.Wire.EX 'STROBE'
Display:M50530-24x8.Wire.GPO 'GND'
Display:M50530-24x8.Wire.IOC1 'SLCTIN'
Display:M50530-24x8.Wire.IOC2 'AUTOFD'
Display:M50530-24x8.Wire.RW 'INIT'
Display:MI240.Driver 'MilfordInstruments'
Display:MI240.Model 'MI240'
Display:MI240.Port '/dev/tts/0'
Display:MI240.Speed 19200
Display:picoLCD.Backlight 1
Display:picoLCD.Contrast 0
Display:picoLCD.Driver 'picoLCD'
Display:picoLCD.Icons 1
Display:picoLCD.Size '20x2'
Display:SC1602D.asc255bug 0
Display:SC1602D.Bits '8'
Display:SC1602D.Driver 'HD44780'
Display:SC1602D.Icons 1
Display:SC1602D.Port '/dev/parports/0'
Display:SC1602D.Size '16x2'
Display:SC1602D.Wire.ENABLE 'STROBE'
Display:SC1602D.Wire.GPO 'INIT'
Display:SC1602D.Wire.POWER 'GND'
Display:SC1602D.Wire.RS 'AUTOFD'
Display:SC1602D.Wire.RW 'GND'
Display:SerDispLib.Driver 'serdisplib'
Display:SerDispLib.Model 'OPTREX323'
Display:SerDispLib.Options ''
Display:SerDispLib.Port 'PAR:/dev/parports/0'
Display:SimpleLCD.Driver 'SimpleLCD'
Display:SimpleLCD.Options 0
Display:SimpleLCD.Port '/dev/tts/0'
Display:SimpleLCD.Size '20x2'
Display:SimpleLCD.Speed 1200
Display:T6963-240x128.Cell 6
Display:T6963-240x128.Driver 'T6963'
Display:T6963-240x128.DualScan 0
Display:T6963-240x128.Font '6x8'
Display:T6963-240x128.Port '/dev/parports/0'
Display:T6963-240x128.Size '240x128'
Display:T6963-240x128.Timing.fuzz 120
Display:T6963-240x128.Wire.CD 'SLCTIN'
Display:T6963-240x128.Wire.CE 'STROBE'
Display:T6963-240x128.Wire.RD 'AUTOFD'
Display:T6963-240x128.Wire.WR 'INIT'
Display:T6963-240x128D.Cell 6
Display:T6963-240x128D.Driver 'T6963'
Display:T6963-240x128D.DualScan 1
Display:T6963-240x128D.Font '6x8'
Display:T6963-240x128D.Port '/dev/parports/0'
Display:T6963-240x128D.Size '240x128'
Display:T6963-240x128D.Timing.fuzz 120
Display:T6963-240x128D.Wire.CD 'SLCTIN'
Display:T6963-240x128D.Wire.CE 'STROBE'
Display:T6963-240x128D.Wire.RD 'AUTOFD'
Display:T6963-240x128D.Wire.WR 'INIT'
Display:T6963-240x64.Cell 6
Display:T6963-240x64.Driver 'T6963'
Display:T6963-240x64.DualScan 0
Display:T6963-240x64.Font '6x8'
Display:T6963-240x64.Port '/dev/parports/0'
Display:T6963-240x64.Size '240x64'
Display:T6963-240x64.Timing.fuzz 120
Display:T6963-240x64.Wire.CD 'SLCTIN'
Display:T6963-240x64.Wire.CE 'STROBE'
Display:T6963-240x64.Wire.RD 'AUTOFD'
Display:T6963-240x64.Wire.WR 'INIT'
Display:Trefon.Backlight 1
Display:Trefon.Driver 'TREFON'
Display:Trefon.Icons 1
Display:Trefon.Size '16x2'
Display:USBLCD.asc255bug 1
Display:USBLCD.Driver 'USBLCD'
Display:USBLCD.Icons 1
Display:USBLCD.Port 'libusb'
Display:USBLCD.Size '20x4'
Display:WDC2704M.Controllers 2
Display:WDC2704M.Driver 'HD44780'
Display:WDC2704M.Model 'generic'
Display:WDC2704M.Port '/dev/parports/0'
Display:WDC2704M.Size '27x4'
Display:WDC2704M.UseBusy 1
Display:WDC2704M.Wire.ENABLE 'STROBE'
Display:WDC2704M.Wire.ENABLE2 'SLCTIN'
Display:WDC2704M.Wire.GPO 'GND'
Display:WDC2704M.Wire.POWER 'GND'
Display:WDC2704M.Wire.RS 'INIT'
Display:WDC2704M.Wire.RW 'AUTOFD'
Display:XWindow.Background '00000022'
Display:XWindow.Basecolor '80d000'
Display:XWindow.Border 20
Display:XWindow.Driver 'X11'
Display:XWindow.Font '5x8'
Display:XWindow.Foreground '000000cc'
Display:XWindow.Gap '-1x-1'
Display:XWindow.Pixel '4+1'
Display:XWindow.Size '120x32'
Layout 'L20x2'
Layout:Debug.Row09.Col1 'Heartbeat'
Layout:Default.Row1.Col1 'OS'
Layout:Default.Row2.Col1 'CPU'
Layout:Default.Row2.Col10 'RAM'
Layout:Default.Row3.Col1 'Busy'
Layout:Default.Row3.Col10 'Rain'
Layout:Default.Row3.Col11 'BusyBar'
Layout:Default.Row4.Col1 'Load'
Layout:Default.Row4.Col11 'LoadBar'
Layout:Default.Row5.Col1 'Disk'
Layout:Default.Row5.Col11 'DiskBar'
Layout:Default.Row6.Col1 'Eth0'
Layout:Default.Row6.Col11 'Eth0Bar'
Layout:L16x1.Row1.Col1 'Busy'
Layout:L16x1.Row1.Col11 'BusyBar'
Layout:L16x2.Row1.Col1 'Busy'
Layout:L16x2.Row1.Col11 'BusyBar'
Layout:L16x2.Row2.Col1 'Disk'
Layout:L16x2.Row2.Col11 'BarTest'
Layout:L20x2.Row1.Col1 'CPUinfo'
Layout:L20x2.Row2.Col1 'Busy'
Layout:L20x2.Row2.Col11 'BusyBar'
Layout:L24x8.Row1.Col1 'Load'
Layout:L24x8.Row1.Col11 'BusyBar'
Layout:L40x2.Row1.Col1 'OS'
Layout:L40x2.Row1.Col21 'Busy'
Layout:L40x2.Row1.Col31 'BusyBar'
Layout:L40x2.Row2.Col1 'CPU'
Layout:L40x2.Row2.Col10 'RAM'
Layout:L40x2.Row2.Col21 'Load'
Layout:L40x2.Row2.Col31 'LoadBar'
Layout:L8x2.Row1.Col1 'Busy'
Layout:L8x2.Row2.Col1 'BarTest'
Layout:Test.Row01.Col1 'Test1'
Layout:Test.Row02.Col1 'Test1'
Layout:Test.Row03.Col1 'Test1'
Layout:Test.Row04.Col1 'Test1'
Layout:Test.Row05.Col1 'Test1'
Layout:Test.Row06.Col1 'Test1'
Layout:Test.Row07.Col1 'Test1'
Layout:Test.Row08.Col1 'Test1'
Layout:Test.Row09.Col1 'Test1'
Layout:Test.Row10.Col1 'Test1'
Layout:Test.Row11.Col1 'Test1'
Layout:Test.Row12.Col1 'Test1'
Layout:Test.Row13.Col1 'Test1'
Layout:Test.Row14.Col1 'Test1'
Layout:Test.Row15.Col1 'Test1'
Layout:Test.Row16.Col1 'Test1'
Layout:Test.Row17.Col1 'Test1'
Layout:Test.Row18.Col1 'Test1'
Layout:Test.Row19.Col1 'Test1'
Layout:Test.Row20.Col1 'Test1'
Layout:Test.Row21.Col1 'Test1'
Layout:Test.Row22.Col1 'Test1'
Layout:Test.Row23.Col1 'Test1'
Layout:Test.Row24.Col1 'Test1'
Layout:Test2.Row01.Col1 'Test1'
Layout:Test2.Row02.Col1 'Test2'
Layout:Test2.Row03.Col1 'Test1'
Layout:Test2.Row04.Col1 'Test2'
Layout:Test2.Row05.Col1 'Test1'
Layout:Test2.Row06.Col1 'Test2'
Layout:Test2.Row07.Col1 'Test1'
Layout:Test2.Row08.Col1 'Test2'
Layout:TestGPO.GPO1 'GPO_Test255'
Layout:TestGPO.GPO4 'GPO_Test1'
Layout:TestGPO.Row1.Col1 'GPO_Val1'
Layout:TestGPO.Row1.Col10 'GPI_Val1'
Layout:TestGPO.Row2.Col1 'GPO_Val4'
Layout:TestIcons.Row1.Col1 'Timer'
Layout:TestIcons.Row1.Col2 'Rain'
Layout:TestIcons.Row1.Col3 'Squirrel'
Layout:TestIcons.Row1.Col4 'Wave'
Layout:TestIcons.Row1.Col5 'Blob'
Layout:TestIcons.Row1.Col6 'Heart'
Layout:TestIcons.Row1.Col7 'Karo'
Layout:TestIcons.Row1.Col8 'EKG'
Layout:TestImage.Layer:2.X1.Y1 'ImageTest'
Layout:TestLayer.Layer:2.X1.Y1 'ImageTest'
Layout:TestLayer.Row1.Col1 'OS'
Layout:TestLayer.Row2.Col1 'CPU'
Layout:TestLayer.Row2.Col10 'RAM'
Layout:TestLayer.Row3.Col1 'Busy'
Layout:TestLayer.Row3.Col10 'Rain'
Layout:TestLayer.Row3.Col11 'BusyBar'
Layout:TestLayer.Row4.Col1 'Load'
Layout:TestLayer.Row4.Col11 'LoadBar'
Layout:TestLayer.Row5.Col1 'Disk'
Layout:TestLayer.Row5.Col11 'DiskBar'
Layout:TestLayer.Row6.Col1 'Eth0'
Layout:TestLayer.Row6.Col11 'Eth0Bar'
Layout:testMySQL.Row1.Col1 'MySQLtest1'
Layout:testMySQL.Row2.Col1 'MySQLtest2'
Plugin:MySQL.database 'lcd4linux'
Plugin:MySQL.password 'lcd4linux'
Plugin:MySQL.port 3306
Plugin:MySQL.server 'gsmlandia.com'
Plugin:MySQL.user 'lcd4linux'
Plugin:Pop3.password1 'secret'
Plugin:Pop3.port1 110
Plugin:Pop3.server1 'localhost'
Plugin:Pop3.user1 'michael'
Plugin:Seti.Directory '/root/setiathome-3.08.i686-pc-linux-gnu'
Variables.minute 60000
Variables.tack 100
Variables.tick 500
Widget:BarTest.class 'Bar'
Widget:BarTest.direction 'E'
Widget:BarTest.expression test::bar(0,30,25,1)
Widget:BarTest.expression2 test::bar(1,30,0,1)
Widget:BarTest.length 8
Widget:BarTest.update 10
Widget:BarTestVal.class 'Text'
Widget:BarTestVal.expression test::bar(0,100,50,0)
Widget:BarTestVal.prefix 'Test '
Widget:BarTestVal.update 200
Widget:BarTestVal.width 9
Widget:Blob.Bitmap.Row1 '.....|.....|.....'
Widget:Blob.Bitmap.Row2 '.....|.....|.***.'
Widget:Blob.Bitmap.Row3 '.....|.***.|*...*'
Widget:Blob.Bitmap.Row4 '..*..|.*.*.|*...*'
Widget:Blob.Bitmap.Row5 '.....|.***.|*...*'
Widget:Blob.Bitmap.Row6 '.....|.....|.***.'
Widget:Blob.Bitmap.Row7 '.....|.....|.....'
Widget:Blob.Bitmap.Row8 '.....|.....|.....'
Widget:Blob.class 'Icon'
Widget:Blob.speed 250
Widget:Busy.align 'R'
Widget:Busy.class 'Text'
Widget:Busy.expression proc_stat::cpu('busy', 500)
Widget:Busy.postfix '%'
Widget:Busy.precision 1
Widget:Busy.prefix 'Busy'
Widget:Busy.update tick
Widget:Busy.width 9
Widget:BusyBar.class 'Bar'
Widget:BusyBar.direction 'E'
Widget:BusyBar.expression proc_stat::cpu('busy', 500)
Widget:BusyBar.expression2 proc_stat::cpu('system', 500)
Widget:BusyBar.length 10
Widget:BusyBar.update tack
Widget:CPU.align 'L'
Widget:CPU.class 'Text'
Widget:CPU.expression uname('machine')
Widget:CPU.prefix 'CPU '
Widget:CPU.style test::onoff(7)>0?'bold':'norm'
Widget:CPU.update tick
Widget:CPU.width 9
Widget:CPUinfo.align 'M'
Widget:CPUinfo.class 'Text'
Widget:CPUinfo.expression cpuinfo('model name')
Widget:CPUinfo.prefix ''
Widget:CPUinfo.speed 100
Widget:CPUinfo.update tick
Widget:CPUinfo.width 20
Widget:Disk.align 'R'
Widget:Disk.class 'Text'
Widget:Disk.expression diskstats('hd.', 'read_sectors', 500) + diskstats('hd.', 'write_sectors', 500)
Widget:Disk.postfix ' '
Widget:Disk.precision 0
Widget:Disk.prefix 'disk'
Widget:Disk.update tick
Widget:Disk.width 10
Widget:DiskBar.class 'Bar'
Widget:DiskBar.direction 'E'
Widget:DiskBar.expression diskstats('hd.', 'read_sectors', 500)
Widget:DiskBar.expression2 diskstats('hd.', 'write_sectors', 500)
Widget:DiskBar.length 14
Widget:DiskBar.update tack
Widget:EKG.Bitmap.Row1 '.....|.....|.....|.....|.....|.....|.....|.....'
Widget:EKG.Bitmap.Row2 '.....|....*|...*.|..*..|.*...|*....|.....|.....'
Widget:EKG.Bitmap.Row3 '.....|....*|...*.|..*..|.*...|*....|.....|.....'
Widget:EKG.Bitmap.Row4 '.....|....*|...**|..**.|.**..|**...|*....|.....'
Widget:EKG.Bitmap.Row5 '.....|....*|...**|..**.|.**..|**...|*....|.....'
Widget:EKG.Bitmap.Row6 '.....|....*|...*.|..*.*|.*.*.|*.*..|.*...|*....'
Widget:EKG.Bitmap.Row7 '*****|*****|****.|***..|**..*|*..**|..***|.****'
Widget:EKG.Bitmap.Row8 '.....|.....|.....|.....|.....|.....|.....|.....'
Widget:EKG.class 'Icon'
Widget:EKG.speed 50
Widget:Eth0.align 'R'
Widget:Eth0.class 'Text'
Widget:Eth0.expression (netdev('eth0', 'Rx_bytes', 500)+netdev('eth0', 'Tx_bytes', 500))/1024
Widget:Eth0.postfix ' '
Widget:Eth0.precision 0
Widget:Eth0.prefix 'eth0'
Widget:Eth0.update tick
Widget:Eth0.width 10
Widget:Eth0Bar.class 'Bar'
Widget:Eth0Bar.direction 'E'
Widget:Eth0Bar.expression netdev('eth0', 'Rx_bytes', 500)
Widget:Eth0Bar.expression2 netdev('eth0', 'Tx_bytes', 500)
Widget:Eth0Bar.length 14
Widget:Eth0Bar.update tack
Widget:GPI_Val1.align 'R'
Widget:GPI_Val1.class 'Text'
Widget:GPI_Val1.expression LCD::GPI(1)
Widget:GPI_Val1.precision 0
Widget:GPI_Val1.prefix 'GPI#1'
Widget:GPI_Val1.update tick
Widget:GPI_Val1.width 10
Widget:GPO_Test1.class 'GPO'
Widget:GPO_Test1.expression 255*test::onoff(1)
Widget:GPO_Test1.update 300
Widget:GPO_Test255.class 'GPO'
Widget:GPO_Test255.expression test::bar(0,255, 0, 1)
Widget:GPO_Test255.update 100
Widget:GPO_Val1.align 'R'
Widget:GPO_Val1.class 'Text'
Widget:GPO_Val1.expression LCD::GPO(1)
Widget:GPO_Val1.precision 0
Widget:GPO_Val1.prefix 'GPO#1'
Widget:GPO_Val1.update tick
Widget:GPO_Val1.width 10
Widget:GPO_Val4.align 'R'
Widget:GPO_Val4.class 'Text'
Widget:GPO_Val4.expression LCD::GPO(4)
Widget:GPO_Val4.precision 0
Widget:GPO_Val4.prefix 'GPO#4'
Widget:GPO_Val4.update tick
Widget:GPO_Val4.width 10
Widget:Heart.Bitmap.Row1 '.....|.....|.....|.....|.....|.....'
Widget:Heart.Bitmap.Row2 '.*.*.|.....|.*.*.|.....|.....|.....'
Widget:Heart.Bitmap.Row3 '*****|.*.*.|*****|.*.*.|.*.*.|.*.*.'
Widget:Heart.Bitmap.Row4 '*****|.***.|*****|.***.|.***.|.***.'
Widget:Heart.Bitmap.Row5 '.***.|.***.|.***.|.***.|.***.|.***.'
Widget:Heart.Bitmap.Row6 '.***.|..*..|.***.|..*..|..*..|..*..'
Widget:Heart.Bitmap.Row7 '..*..|.....|..*..|.....|.....|.....'
Widget:Heart.Bitmap.Row8 '.....|.....|.....|.....|.....|.....'
Widget:Heart.class 'Icon'
Widget:Heart.speed 250
Widget:Heartbeat.Bitmap.Row1 '.....|.....'
Widget:Heartbeat.Bitmap.Row2 '.*.*.|.*.*.'
Widget:Heartbeat.Bitmap.Row3 '*****|*.*.*'
Widget:Heartbeat.Bitmap.Row4 '*****|*...*'
Widget:Heartbeat.Bitmap.Row5 '.***.|.*.*.'
Widget:Heartbeat.Bitmap.Row6 '.***.|.*.*.'
Widget:Heartbeat.Bitmap.Row7 '..*..|..*..'
Widget:Heartbeat.Bitmap.Row8 '.....|.....'
Widget:Heartbeat.class 'Icon'
Widget:Heartbeat.speed 800
Widget:ImageTest.class 'Image'
Widget:ImageTest.file 'tux.png'
Widget:ImageTest.inverted 0
Widget:ImageTest.update 1000
Widget:ImageTest.visible 1
Widget:Karo.Bitmap.Row1 '.....|.....|.....|.....|..*..|.....|.....|.....'
Widget:Karo.Bitmap.Row2 '.....|.....|.....|..*..|.*.*.|..*..|.....|.....'
Widget:Karo.Bitmap.Row3 '.....|.....|..*..|.*.*.|*...*|.*.*.|..*..|.....'
Widget:Karo.Bitmap.Row4 '.....|..*..|.*.*.|*...*|.....|*...*|.*.*.|..*..'
Widget:Karo.Bitmap.Row5 '.....|.....|..*..|.*.*.|*...*|.*.*.|..*..|.....'
Widget:Karo.Bitmap.Row6 '.....|.....|.....|..*..|.*.*.|..*..|.....|.....'
Widget:Karo.Bitmap.Row7 '.....|.....|.....|.....|..*..|.....|.....|.....'
Widget:Karo.Bitmap.Row8 '.....|.....|.....|.....|.....|.....|.....|.....'
Widget:Karo.class 'Icon'
Widget:Karo.speed 200
Widget:KVV.align 'L'
Widget:KVV.class 'Text'
Widget:KVV.expression kvv::line(0).' '.kvv::station(0)
Widget:KVV.Foreground 'ffff00'
Widget:KVV.style 'bold'
Widget:KVV.update tick
Widget:KVV.width 11
Widget:KVV_TIME.align 'R'
Widget:KVV_TIME.class 'Text'
Widget:KVV_TIME.expression kvv::time_str(0)
Widget:KVV_TIME.foreground kvv::time(0) < 2 ? 'FF0000' : ( kvv::time(0) < 5 ? 'FFFF00' : '00FF00' )
Widget:KVV_TIME.style 'bold'
Widget:KVV_TIME.update tick
Widget:KVV_TIME.width 2
Widget:Lightning.bitmap.row1 '...***'
Widget:Lightning.bitmap.row2 '..***.'
Widget:Lightning.bitmap.row3 '.***..'
Widget:Lightning.bitmap.row4 '.****.'
Widget:Lightning.bitmap.row5 '..**..'
Widget:Lightning.bitmap.row6 '.**...'
Widget:Lightning.bitmap.row7 '**....'
Widget:Lightning.bitmap.row8 '*.....'
Widget:Lightning.class 'icon'
Widget:Lightning.speed 100
Widget:Lightning.visible cpu('busy', 500)-50
Widget:LightningTest.bitmap.row1 '...***'
Widget:LightningTest.bitmap.row2 '..***.'
Widget:LightningTest.bitmap.row3 '.***..'
Widget:LightningTest.bitmap.row4 '.****.'
Widget:LightningTest.bitmap.row5 '..**..'
Widget:LightningTest.bitmap.row6 '.**...'
Widget:LightningTest.bitmap.row7 '**....'
Widget:LightningTest.bitmap.row8 '*.....'
Widget:LightningTest.class 'icon'
Widget:LightningTest.speed 500
Widget:LightningTest.visible test::onoff(0)
Widget:Load.align 'R'
Widget:Load.class 'Text'
Widget:Load.expression loadavg(1)
Widget:Load.postfix loadavg(1)>1.0?'!':' '
Widget:Load.precision 1
Widget:Load.prefix 'Load'
Widget:Load.update tick
Widget:Load.width 10
Widget:LoadBar.class 'Bar'
Widget:LoadBar.direction 'E'
Widget:LoadBar.expression loadavg(1)
Widget:LoadBar.length 10
Widget:LoadBar.max 2.0
Widget:LoadBar.update tack
Widget:MySQLtest1.align 'R'
Widget:MySQLtest1.class 'Text'
Widget:MySQLtest1.expression MySQL::query('SELECT id FROM table1')
Widget:MySQLtest1.prefix 'MySQL test:'
Widget:MySQLtest1.update minute
Widget:MySQLtest1.width 20
Widget:MySQLtest2.align 'M'
Widget:MySQLtest2.class 'Text'
Widget:MySQLtest2.expression MySQL::status()
Widget:MySQLtest2.prefix 'Status: '
Widget:MySQLtest2.update minute
Widget:MySQLtest2.width 20
Widget:OS.align 'M'
Widget:OS.class 'Text'
Widget:OS.expression '*** '.uname('sysname').' '.uname('release').' ***'
Widget:OS.speed 50
Widget:OS.style 'bold'
Widget:OS.update tick
Widget:OS.width 20
Widget:PPP.align 'R'
Widget:PPP.class 'Text'
Widget:PPP.expression (ppp('Rx:0', 500)+ppp('Tx:0', 500))
Widget:PPP.precision 0
Widget:PPP.prefix 'PPP'
Widget:PPP.update tick
Widget:PPP.width 9
Widget:Rain.bitmap.row1 '...*.|.....|.....|.*...|....*|..*..|.....|*....'
Widget:Rain.bitmap.row2 '*....|...*.|.....|.....|.*...|....*|..*..|.....'
Widget:Rain.bitmap.row3 '.....|*....|...*.|.....|.....|.*...|....*|..*..'
Widget:Rain.bitmap.row4 '..*..|.....|*....|...*.|.....|.....|.*...|....*'
Widget:Rain.bitmap.row5 '....*|..*..|.....|*....|...*.|.....|.....|.*...'
Widget:Rain.bitmap.row6 '.*...|....*|..*..|.....|*....|...*.|.....|.....'
Widget:Rain.bitmap.row7 '.....|.*...|....*|..*..|.....|*....|...*.|.....'
Widget:Rain.bitmap.row8 '.....|.....|.*...|....*|..*..|.....|*....|...*.'
Widget:Rain.class 'icon'
Widget:Rain.speed 200
Widget:RAM.align 'R'
Widget:RAM.class 'Text'
Widget:RAM.expression meminfo('MemTotal')/1024
Widget:RAM.postfix ' MB RAM'
Widget:RAM.precision 0
Widget:RAM.update tick
Widget:RAM.width 11
Widget:Squirrel.Bitmap.Row1 '.....|.....|.....|.....|.....|.....'
Widget:Squirrel.Bitmap.Row2 '.....|.....|.....|.....|.....|.....'
Widget:Squirrel.Bitmap.Row3 '.....|.....|.....|.....|.....|.....'
Widget:Squirrel.Bitmap.Row4 '**...|.**..|..**.|...**|....*|.....'
Widget:Squirrel.Bitmap.Row5 '*****|*****|*****|*****|*****|*****'
Widget:Squirrel.Bitmap.Row6 '...**|..**.|.**..|**...|*....|.....'
Widget:Squirrel.Bitmap.Row7 '.....|.....|.....|.....|.....|.....'
Widget:Squirrel.Bitmap.Row8 '.....|.....|.....|.....|.....|.....'
Widget:Squirrel.class 'Icon'
Widget:Squirrel.speed 100
Widget:Temp.align 'R'
Widget:Temp.class 'Text'
Widget:Temp.expression i2c_sensors('temp_input3')*1.0324-67
Widget:Temp.precision 1
Widget:Temp.prefix 'Temp'
Widget:Temp.update tick
Widget:Temp.width 9
Widget:TempBar.class 'Bar'
Widget:TempBar.direction 'E'
Widget:TempBar.expression i2c_sensors('temp_input3')*1.0324-67
Widget:TempBar.length 10
Widget:TempBar.max 80
Widget:TempBar.min 40
Widget:TempBar.update tack
Widget:Test.class 'Text'
Widget:Test.expression '1234567890123456789012345678901234567890'
Widget:Test.foreground 'ff0000ff'
Widget:Test.width 40
Widget:Test1.align 'M'
Widget:Test1.class 'Text'
Widget:Test1.expression 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
Widget:Test1.speed 100
Widget:Test1.width 40
Widget:Test2.align 'M'
Widget:Test2.class 'Text'
Widget:Test2.expression '1234567890abcdefghijklmnopqrstuvwxyz'
Widget:Test2.speed 150
Widget:Test2.width 40
Widget:Timer.Bitmap.Row1 '.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|'
Widget:Timer.Bitmap.Row2 '.***.|.*+*.|.*++.|.*++.|.*++.|.*++.|.*++.|.*++.|.*++.|.*++.|.*++.|.*++.|.+++.|.+*+.|.+**.|.+**.|.+**.|.+**.|.+**.|.+**.|.+**.|.+**.|.+**.|.+**.|'
Widget:Timer.Bitmap.Row3 '*****|**+**|**++*|**+++|**++.|**++.|**+++|**+++|**+++|**+++|**+++|+++++|+++++|++*++|++**+|++***|++**.|++**.|++***|++***|++***|++***|++***|*****|'
Widget:Timer.Bitmap.Row4 '*****|**+**|**+**|**+**|**+++|**+++|**+++|**+++|**+++|**+++|+++++|+++++|+++++|++*++|++*++|++*++|++***|++***|++***|++***|++***|++***|*****|*****|'
Widget:Timer.Bitmap.Row5 '*****|*****|*****|*****|*****|***++|***++|**+++|*++++|+++++|+++++|+++++|+++++|+++++|+++++|+++++|+++++|+++**|+++**|++***|+****|*****|*****|*****|'
Widget:Timer.Bitmap.Row6 '.***.|.***.|.***.|.***.|.***.|.***.|.**+.|.*++.|.+++.|.+++.|.+++.|.+++.|.+++.|.+++.|.+++.|.+++.|.+++.|.+++.|.++*.|.+**.|.***.|.***.|.***.|.***.|'
Widget:Timer.Bitmap.Row7 '.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|'
Widget:Timer.Bitmap.Row8 '.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|.....|'
Widget:Timer.class 'Icon'
Widget:Timer.speed 50
Widget:Uptime.align 'R'
Widget:Uptime.class 'Text'
Widget:Uptime.expression uptime('%d days %H:%M:%S')
Widget:Uptime.prefix 'Up '
Widget:Uptime.update 1000
Widget:Uptime.width 20
Widget:Wave.Bitmap.Row1 '..**.|.**..|**...|*....|.....|.....|.....|.....|....*|...**'
Widget:Wave.Bitmap.Row2 '.*..*|*..*.|..*..|.*...|*....|.....|.....|....*|...*.|..*..'
Widget:Wave.Bitmap.Row3 '*....|....*|...*.|..*..|.*...|*....|....*|...*.|..*..|.*...'
Widget:Wave.Bitmap.Row4 '*....|....*|...*.|..*..|.*...|*....|....*|...*.|..*..|.*...'
Widget:Wave.Bitmap.Row5 '*....|....*|...*.|..*..|.*...|*....|....*|...*.|..*..|.*...'
Widget:Wave.Bitmap.Row6 '.....|.....|....*|...*.|..*..|.*..*|*..*.|..*..|.*...|*....'
Widget:Wave.Bitmap.Row7 '.....|.....|.....|....*|...**|..**.|.**..|**...|*....|.....'
Widget:Wave.Bitmap.Row8 '.....|.....|.....|.....|.....|.....|.....|.....|.....|.....'
Widget:Wave.class 'Icon'
Widget:Wave.speed 100

plugin_cfg.c: Variable minute = '60000' (60000)
plugin_cfg.c: Variable tack = '100' (100)
plugin_cfg.c: Variable tick = '500' (500)
lcd4linux.c: initializing driver picoLCD
drv_init(picoLCD) failed: no such driver
Error initializing driver picoLCD: Exit!
root@OpenWrt:/#

Что-то не получилось. Сообщение drv_init(picoLCD) failed: no such driver говорит нам о том, что выбран не тот тип дисплея. Для конфигурации lcd4linux открываем через vi файл /etc/lcd4linux.conf и немного поправим его.

Закомментарим строку Display 'picoLCD':
#Display 'picoLCD'

Разкомментарим строку #Display 'LCD2USB':
Display 'LCD2USB'

Пробуем снова:

root@OpenWrt:/# lcd4linux -Fvv
LCD4Linux 0.11.0-SVN-1092 starting
security error: group or other have access to '/etc/lcd4linux.conf'

Снова не получилось. Нужно изменить права для файла /etc/lcd4linux.conf

root@OpenWrt:/# chmod 600 /etc/lcd4linux.conf

Запускаем еще раз:

root@OpenWrt:/# lcd4linux -Fv
LCD4Linux 0.11.0-SVN-1092 starting
LCD2USB: $Rev: 975 $
LCD2USB: scanning USB for LCD2USB interface ...
LCD2USB: found LCD2USB interface on bus 001 device 005
LCD2USB: echo test successful
LCD2USB: firmware version 1.09
LCD2USB: installed controllers: CTRL0
LCD2USB: reserving 1 of 8 user-defined characters for icons
initializing layout 'L20x2'
Creating new timer group (500 ms)
widget 'Load': Class 'text', Parent '', Layer 1, Row 0, Col 0 (to 0,10)
Creating new timer group (100 ms)
widget 'LoadBar': Class 'bar', Parent '', Layer 1, Row 0, Col 10 (to 0,19)
widget 'Busy': Class 'text', Parent '', Layer 1, Row 1, Col 0 (to 1,9)
widget 'BusyBar': Class 'bar', Parent '', Layer 1, Row 1, Col 10 (to 1,19)

Красота! Ну а выглядеть примерно должно вот так:

Usb2Lcd - open-source проект, и поэтому его можно собрать самому