diff --git a/CREDITS b/CREDITS index 464ff11..58b9c64 100644 --- a/CREDITS +++ b/CREDITS @@ -220,6 +220,9 @@ Frank Jepsen Karsten Festag - ea65 driver +Gatewood Green + - picolcd driver + Further developers in the sourceforge lcdproc team: Mindaugas Idzelis aim4min diff --git a/ChangeLog b/ChangeLog index b2c32ff..3ff92ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,6 +34,7 @@ v.0.5dev (ongoing development) + new 2-line bignum mode using 6 user defined characters (Robin Gilks) * fix custom characters [with NewFirmware=yes] & backlight in CFontz + ea65 - driver for VFD in AOpen XC Cube AV EA65 barebones (Karsten Festag) + + picolcd - driver for Mini-box.com USB LCD picoLCD (Gatewood Green) v.0.5.1 + config file support in lcdproc client (Andrew Foss) diff --git a/LCDd.conf b/LCDd.conf index 5eeec9e..82b48db 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -36,10 +36,10 @@ # driver specific section. # # The following drivers are supported: -# bayrad, CFontz, CFontz633, CFontzPacket, curses, CwLnx, EyeboxOne, -# g15, glcdlib, glk, hd44780, icp_a106, imon, IOWarrior, irman, -# joy, lb216,lcdm001, lcterm, lirc,MD8800, ms6931, mtc_s16209x, -# MtxOrb, NoritakeVFD, pyramid, sed1330, sed1520, serialPOS, +# bayrad, CFontz, CFontz633, CFontzPacket, curses, CwLnx, ea65, +# EyeboxOne, g15, glcdlib, glk, hd44780, icp_a106, imon, IOWarrior, +# irman, joy, lb216,lcdm001, lcterm, lirc,MD8800, ms6931, mtc_s16209x, +# MtxOrb, NoritakeVFD, picolcd, pyramid, sed1330, sed1520, serialPOS, # serialVFD, sli, stv5730, svga, t6963, text, tyan, ula200, xosd Driver=curses @@ -279,6 +279,7 @@ Keypad=yes #keypad_test_mode=yes + ## ea65 driver for the display in AOpen XC Cube AV EA65 media barebones ## [ea65] @@ -295,6 +296,7 @@ Brightness=500 OffBrightness=0 + ## EyeboxOne driver ## [EyeboxOne] @@ -329,6 +331,7 @@ EscapeKey=P keypad_test_mode=no + ## g15 driver for Logitech G15 Keyboard LCDs ## [g15] @@ -357,7 +360,6 @@ TextResolution=20x4 # path to font file to use FontFile=/usr/share/fonts/corefonts/courbd.ttf - ## these only apply if UseFT2=yes: # character encoding to use @@ -366,7 +368,6 @@ CharEncoding=iso8859-2 # minumum size in pixels in which fonts should be rendered MinFontFaceSize=7x12 - ## optional: Brightness=50 # Brightness (in %) if applicable Contrast=50 # Contrast (in %) if applicable @@ -709,6 +710,38 @@ Speed=9600 +## Mini-box.com picoLCD (usblcd) driver ## +[picolcd] +# This is for the Mini-Box.com usblcd device that ships with the M300. It can +# also be purchased separately but this driver has only been tested on the M300 +# setup. + +# KeyTimeout is the time that LCDd spends waiting for a key press before cycling +# through other duties. Higher values make LCDd use less CPU time and make +# key presses more detectable. Lower values make LCDd more responsive but a +# little prone to missing key presses. 500 (.5 second) is the default and a +# balanced value. +KeyTimeout=500 + +# Contrast: [default: 1000; legal: 0 - 1000] +Contrast=1000 + +# Light the keys? i[default: on; legal: on, off] +Keylights=on + +# If Keylights is on, the you can unlight specific keys below: +# Key0 is the directional pad. Key1 - Key5 correspond to the F1 - F5 keys. +# There is no LED for the +/- keys. This is a handy way to indicate to users +# which keys are disabled. [default: on; legal: on, off] +Key0Light=on +Key1Light=on +Key2Light=on +Key3Light=on +Key4Light=on +Key5Light=on + + + ## Pyramid LCD driver ## [pyramid] diff --git a/acinclude.m4 b/acinclude.m4 index 88b71a9..ff62658 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -5,17 +5,18 @@ AC_ARG_ENABLE(drivers, [ --enable-drivers= compile drivers for LCDs in ,] [ which is a comma-separated list of drivers.] [ Possible drivers are:] - [ bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,] - [ g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,irman,] - [ joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,mtc_s16209x,] - [ MtxOrb,NoritakeVFD,pyramid,sed1330,sed1520,serialPOS,] - [ serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd] + [ bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,] + [ EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,] + [ irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,] + [ mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330] + [ sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,] + [ tyan,ula200,xosd] [ 'all' compiles all drivers;] [ 'all,!xxx,!yyy' de-selects previously selected drivers], drivers="$enableval", drivers=[bayrad,CFontz,CFontz633,curses,CwLnx,glk,lb216,lcdm001,MtxOrb,pyramid,text]) -allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,mtc_s16209x,MtxOrb,NoritakeVFD,pyramid,sed1330,sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd] +allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd] drivers=`echo $drivers | sed -e 's/,/ /g'` @@ -275,6 +276,23 @@ dnl else DRIVERS="$DRIVERS NoritakeVFD${SO}" actdrivers=["$actdrivers NoritakeVFD"] ;; + picolcd) + AC_CHECK_HEADERS([usblcd.h],[ + AC_CHECK_LIB(usblcd, main,[ + LIBUSBLCD="-lusblcd" + DRIVERS="$DRIVERS picolcd${SO}" + actdrivers=["$actdrivers picolcd"] + ],[ +dnl else + AC_MSG_WARN([The picolcd driver needs the usblcd library]) + ], + [-lusblcd] + ) + ],[ +dnl else + AC_MSG_WARN([The picolcd driver needs widgets.h, usblcd.h and usblcd_util.h from the usblcd package]) + ]) + ;; pyramid) DRIVERS="$DRIVERS pyramid${SO}" actdrivers=["$actdrivers pyramid"] @@ -399,6 +417,7 @@ AC_SUBST(LIBG15) AC_SUBST(LIBGLCD) AC_SUBST(LIBFTDI) AC_SUBST(LIBXOSD) +AC_SUBST(LIBUSBLCD) ]) diff --git a/docs/LCDd.8.in b/docs/LCDd.8.in index 5a4a5f8..2654a52 100644 --- a/docs/LCDd.8.in +++ b/docs/LCDd.8.in @@ -195,6 +195,9 @@ Matrix Orbital displays (except Matrix Orbital GLK displays) .B NoritakeVFD Noritake VFD Device CU20045SCPB-T28A .TP +.B picolcd +Mini-box.com USB LCD (picoLCD 20x2) +.TP .B pyramid LCD displays from Pyramid (http://www.pyramid.de) .TP diff --git a/docs/lcdproc-user/drivers.docbook b/docs/lcdproc-user/drivers.docbook index 7a6cdb4..2060d72 100644 --- a/docs/lcdproc-user/drivers.docbook +++ b/docs/lcdproc-user/drivers.docbook @@ -33,6 +33,7 @@ well as the configuration of LCDd. &mtc_s16209x; &MtxOrb; &NoritakeVFD; +&picolcd; &pylcd; &sed1330; &sed1520; diff --git a/docs/lcdproc-user/drivers/picolcd.docbook b/docs/lcdproc-user/drivers/picolcd.docbook new file mode 100644 index 0000000..03d296f --- /dev/null +++ b/docs/lcdproc-user/drivers/picolcd.docbook @@ -0,0 +1,139 @@ + + The Mini-Box USB LCD (picoLCD 20x2) Driver (picolcd) + + + This section covers the installation and use of the Mini-Box USB LCD (picoLCD + 20x2) display. + + + The picoLCD page indicates that the device can be connected via I2C or USART. + This lcdproc driver, however, is limited to the USB connected model. + + + Setting up the picoLCD + + + The picoLCD device as used by this driver is USB connected and may be purchased + with an internal USB header connector (5-pin to 5-pin) or an external cable + (Type-A to 5-pin). See: http://www.mini-box.com/picoLCD-20x2-OEM. It may also + come pre-installed on systems like the Mini-Box M300: + http://www.mini-box.com/Mini-Box-M300-LCD. + + + Using the USB LCD with this driver requires the usblcd library from Mini-box.com + (avaiable at http://www.mini-box.com/picoLCD-20x2-OEM). The usblcd library + requires libusb and libhcd. Your distribution may or may not already provide + these libraries. The only kernel driver required is the USB host controller + driver (uhci_hcd on the M300) required to fire up the usb bus to which the LCD is + attached. + + + Lastly, the usbfs file system must be mounted on /proc/bus/usb. + mount -t usbfs usbfs /proc/bus/usb + + + Once connected and with libusblcd, libusb and libhid installed, testing the USB LCD + can be done with the "usblcd" program that comes with the usblcd library. You can + also change the USB LCD's initial display (what it shows when you initialize the + device) by using the usblcd binary's "splash" command. + + + To use the picolcd with lcdproc, add picolcd to the lcdproc configure drivers option + (or use all) and then start LCDd with the "-d picolcd" option. The driver has + sane default options and the options that are user configurable are limited to mostly + simple items, like contrast and which keys to lights up. + + + + + Contrast: 0-1000. 0 is visible, and 1000 is not on my M300. Default is 0. + + + Keylights: 0/1. 0 turns off the key LEDs and 1 turns them on. Default is 1. + + + + + Key0Light: if Keylights is set to 1, you can disable the directional pad LED by + setting this value to 0. Default is 1. + + + + + Key1Light: if Keylights is set to 1, you can disable the F1 LED by setting this value + to 0. Default is 1. + + + + + Key2Light: if Keylights is set to 1, you can disable the F2 LED by setting this value + to 0. Default is 1. + + + + + Key3Light: if Keylights is set to 1, you can disable the F3 LED by setting this value + to 0. Default is 1. + + + + + Key4Light: if Keylights is set to 1, you can disable the F4 LED by setting this value + to 0. Default is 1. + + + + + Key5Light: if Keylights is set to 1, you can disable the F5 LED by setting this value + to 0. Default is 1. + + + + + KeyTimeout: (Advanced) This value controls how long LCDd waits for a key press when + get_key is called. The value represents microseconds and the default is 500 or .5 + seconds. Lowering this value will make LCDd more responsive but also causes LCDd to use + more CPU time and, as the timeout grows shorter, key presses become harder to detect. + Larger values make key presses more reliable if somewhat slow to take effect. + + + + picolcd driver status + + + The lcdproc picolcd driver relies upon Mini-Box's usblcd library to setup the USB/HID + interface. Unfortunately the usblcd library is very thin and tends to put function + results on stdout/stderr instead of in return values. They (Mini-Box) really had + scripting interfaces in mind. + + + The primary example of this is that I had to write a replacement (get_key_events) for + usblcd's read_events so that I could get the key presses back to the calling function + instead of on stdout. usblcd also has a large number of function shells for which no + code exists yet. I am not an expert on HID and USB coding, but if and as time permits + and hardware is available I will try and improve this drivers access to the hardware in + order to get back data (get_contrast for example) and to potentially drive multiple + pcioLCDs at once (or pick the one we want out of many). + + + To sum up, this driver right now stabs and hopes since response data is lacking. + + + The hardware also reports key-up events. Normally this would be of no issue (they are + usually a 0 or 'no key') except that when keys are used in combonation, the key-up + event may actually come back as multiple events depending on how the user released the + keys. If the key-up event for a multiple key press comes back as two events, the first + up event will actually look like a new key press. The algorithm in get_key tries to + deal with this in a sane way and toss out all key-up events for now. The hardware is + touchy and both combo key-down and key-up actions may be reported as mutiple events if + the user is more than a tenth of a second (maybe less?) off in motions. + + + + Copyright + + The lcdproc picolcd driver was written by Gatewood Green (woody@nitrosecurity.com) + or (woody@linif.org) and paid for by NitroSecurity, Inc (nitrosecurity.com). + + + diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am index 41eb3a2..b2541f0 100644 --- a/server/drivers/Makefile.am +++ b/server/drivers/Makefile.am @@ -19,7 +19,7 @@ AM_LDFLAGS = @LDSHARED@ #LIBS = pkglib_PROGRAMS = @DRIVERS@ -EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon IOWarrior irman joy lb216 lcdm001 lcterm lirc MD8800 ms6931 mtc_s16209x MtxOrb NoritakeVFD pyramid sed1330 sed1520 serialPOS serialVFD stv5730 svga t6963 text tyan sli ula200 xosd +EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon IOWarrior irman joy lb216 lcdm001 lcterm lirc MD8800 ms6931 mtc_s16209x MtxOrb NoritakeVFD picolcd pyramid sed1330 sed1520 serialPOS serialVFD stv5730 svga t6963 text tyan sli ula200 xosd noinst_LIBRARIES = libLCD.a libbignum.a IOWarrior_CFLAGS = @libusb_cflags@ $(AM_CFLAGS) @@ -45,6 +45,7 @@ MD8800_LDADD = libLCD.a mtc_s16209x_LDADD = libLCD.a MtxOrb_LDADD = libLCD.a libbignum.a NoritakeVFD_LDADD = libLCD.a +picolcd_LDADD = libLCD.a @LIBUSBLCD@ pyramid_LDADD = libLCD.a serialPOS_LDADD = libLCD.a libbignum.a serialVFD_LDADD = libLCD.a libbignum.a @@ -86,6 +87,7 @@ ms6931_SOURCES = lcd.h lcd_lib.h ms6931.h ms6931.c report.h mtc_s16209x_SOURCES = lcd.h lcd_lib.h mtc_s16209x.c mtc_s16209x.h report.h MtxOrb_SOURCES = lcd.h lcd_lib.h MtxOrb.c MtxOrb.h report.h adv_bignum.h NoritakeVFD_SOURCES = lcd.h lcd_lib.h NoritakeVFD.c NoritakeVFD.h report.h +picolcd_SOURCES = lcd.h picolcd.h picolcd.c report.h pyramid_SOURCES = lcd.h pylcd.c pylcd.h sed1330_SOURCES = lcd.h sed1330.h sed1330.c port.h lpt-port.h timing.h report.h sed1520_SOURCES = lcd.h sed1520.c sed1520.h sed1520fm.c sed1520fm.h port.h report.h diff --git a/server/drivers/picolcd.c b/server/drivers/picolcd.c new file mode 100644 index 0000000..2a5656f --- /dev/null +++ b/server/drivers/picolcd.c @@ -0,0 +1,520 @@ +/* + * picoLCD driver for lcdPROC + * + * (c) 2007 NitroSecurity, Inc. + * Written by Gatewood Green or + * + * License: GPL (same as usblcd and lcdPROC) + * + * picoLCD: http://www.mini-box.com/picoLCD-20x2-OEM + * Can be purchased separately or preinstalled in units such as the + * M300 http://www.mini-box.com/Mini-Box-M300-LCD + * + * This driver (key lables and arrangement) is based on the M300 implementation + * of the picoLCD + * + * The picoLCD is usb connected and is driven (currently) via userspace + * libraries using the Mini-box.com usblcd library (not to be confused with the + * Linux usblcd module which does NOT support this device). The usblcd library + * rides atop libusb and libhid (both of which are required for this driver to + * operate). + * + * libusb: http://libusb.sf.net + * libhid: http://libhid.alioth.debian.org + * usblcd: http://www.mini-box.com/picoLCD-20x2-OEM + * + * The usblcd library is very haphazardly written and directly writes to + * stdout and stderr instead of returning the result for most functions + * (including read_events). Eventually it would be a good idea to eliminate + * the need for usblcd and drive the hardware via libusb and libhid directly. + * Such a conversion has the opportunity to provide meaningful return values + * for all fucntions (instead of stab and hope) and allow for use of multiple + * picoLCD devices. + * + * Due to the way libusblcd's read_events prints keys to stderr instead of + * returning a struct or some such, you will find my own get_key_events below. + * + * ### WARNING ###: libusblcd.so sets a handler for SIGTERM. Because most + * applications would set up their signal handling early on (before calling + * new_usblcd_operations()), this can result in a condition that will prevent + * a handler your application installed from executing. If your handler was + * responsible for cleaning up logs, syncing, etc, it can result in lost data. + * + */ + +/* lcdPROC includes */ +#include "lcd.h" +#include "picolcd.h" +#include "report.h" + +/* These three includes are the Mini-box.com libusblcd (usblcd) and company. */ +#include +#include +#include + +/* Various odds and ends */ +#include +#include +#include +#include +#include + +/* This is a hack */ +#define API_VERSION "0.5" + +/* 12 keys plus a 0 placeholder */ +#define KEYPAD_MAX 13 +#define KEYPAD_LIGHTS 6 + +#define DEFAULT_CONTRAST 1000 /* Full */ +#define DEFAULT_BACKLIGHT 1 /* On */ +#define DEFAULT_KEYLIGHTS 1 /* On */ +#define DEFAULT_TIMEOUT 500 /* Half second */ + +/* Set this to 1 and get lots of cruft on stderr when using "LCDd -f 1 -d picolcd" */ +#define DEBUG_PICO 0 + +/* PrivateData struct */ +typedef struct pd { + usblcd_operations *lcd; // Reference to the LCD instance + int width; + int height; + int key_timeout; + int contrast; + int backlight; + int keylights; + int key_light[KEYPAD_LIGHTS]; + char *key_matrix[KEYPAD_MAX]; + char *info; + unsigned char *framebuf; + unsigned char *lstframe; +} PrivateData; + +static char * keymap[KEYPAD_MAX] = { + NULL, + "Plus", + "Minus", + "F1", + "F2", + "F3", + "F4", + "F5", + "Left", + "Right", + "Up", + "Down", + "Enter" +}; + +/* Private function definitions */ +void get_key_event ( usblcd_operations *self, lcd_packet *packet, int timeout ); +void set_key_lights ( usblcd_operations *self, int keys[], int state ); + +/* lcd_logical_driver Variables */ +MODULE_EXPORT char *api_version = API_VERSION; +MODULE_EXPORT int stay_in_foreground = 0; +MODULE_EXPORT int supports_multiple = 1; +MODULE_EXPORT char *symbol_prefix = "picoLCD_"; + +/* lcd_logical_driver Manditory functions */ +MODULE_EXPORT int picoLCD_init( Driver *drvthis ) { + PrivateData *pd; + int x; + + pd = ( PrivateData * ) malloc( sizeof( PrivateData ) ); + + if ( ! pd ) + return -1; + + if ( drvthis->store_private_ptr( drvthis, pd ) ) + return -1; + + pd->lcd = new_usblcd_operations(); + pd->lcd->init( pd->lcd ); + pd->width = 20; /* hard coded (mfg spec) */ + pd->height = 2; /* hard coded (mfg spec) */ + pd->info = "picoLCD: Supports the LCD as installed on the M300 (http://www.mini-box.com/Mini-Box-M300-LCD) "; + + for ( x = 0; x < KEYPAD_LIGHTS; x++ ) + pd->key_light[x] = 1; /* individual lights on */ + + pd->contrast = drvthis->config_get_int( drvthis->name, "Contrast", 0, DEFAULT_CONTRAST ); + pd->backlight = drvthis->config_get_bool( drvthis->name, "BackLight", 0, DEFAULT_BACKLIGHT ); + pd->keylights = drvthis->config_get_bool( drvthis->name, "KeyLights", 0, DEFAULT_KEYLIGHTS ); /* key lights with LCD Backlight? */ + pd->key_timeout = drvthis->config_get_int( drvthis->name, "KeyTimeout", 0, DEFAULT_TIMEOUT ); + + /* These allow individual lights to be disabled */ + pd->key_light[0] = drvthis->config_get_bool( drvthis->name, "Key0Light", 0, 1 ); /* Directional PAD */ + pd->key_light[1] = drvthis->config_get_bool( drvthis->name, "Key1Light", 0, 1 ); /* F1 */ + pd->key_light[2] = drvthis->config_get_bool( drvthis->name, "Key2Light", 0, 1 ); /* F2 */ + pd->key_light[3] = drvthis->config_get_bool( drvthis->name, "Key3Light", 0, 1 ); /* F3 */ + pd->key_light[4] = drvthis->config_get_bool( drvthis->name, "Key4Light", 0, 1 ); /* F4 */ + pd->key_light[5] = drvthis->config_get_bool( drvthis->name, "Key5Light", 0, 1 ); /* F5 */ + + for ( x = 0; x < KEYPAD_MAX; x++ ) + pd->key_matrix[x] = keymap[x]; + + pd->framebuf = ( unsigned char * ) malloc( pd->width * pd->height + 1 ); + if ( pd->framebuf == NULL ) { + report( RPT_ERR, "%s: unable to create framebuf.\n", __FUNCTION__ ); + return -1; + } + memset( pd->framebuf, ' ', pd->width * pd->height ); + pd->framebuf[pd->width * pd->height] = 0; + + pd->lstframe = ( unsigned char * ) malloc( pd->width * pd->height + 1 ); + if ( pd->lstframe == NULL ) { + report( RPT_ERR, "%s: unable to create lstframe.\n", __FUNCTION__ ); + return -1; + } + memset( pd->lstframe, ' ', pd->width * pd->height ); + pd->lstframe[pd->width * pd->height] = 0; + + if ( pd->backlight ) + picoLCD_backlight( drvthis, 1 ); + if ( ! pd->keylights ) + set_key_lights( pd->lcd, pd->key_light, 0 ); + else + picoLCD_backlight( drvthis, 0 ); + + picoLCD_set_contrast( drvthis, pd->contrast ); + + report( RPT_INFO, "picolcd: init complete\n", __FUNCTION__ ); + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: init complete\n" ); + + return 0; +} + +MODULE_EXPORT void picoLCD_close( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + + pd->lcd->close( pd->lcd ); /* This actually does not do anything in usblcd (yet?) */ + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: close complete\n" ); +} + +/* lcd_logical_driver Essential output functions */ +MODULE_EXPORT int picoLCD_width( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + + return pd->width; +} + +MODULE_EXPORT int picoLCD_height( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + + return pd->height; +} + +MODULE_EXPORT void picoLCD_clear( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + + memset( pd->framebuf, ' ', pd->width * pd->height ); + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: clear complete\n" ); +} + +MODULE_EXPORT void picoLCD_flush( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + unsigned char *fb = pd->framebuf; + unsigned char *lf = pd->lstframe; + static char text[48]; + int i, line, offset; + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: flush started\n" ); + + for ( line = 0; line < pd->height; line++ ) { + memset( text, 0, 48 ); + offset = line * pd->width; + fb = pd->framebuf + offset; + lf = pd->lstframe + offset; + + for ( i = 0; i < pd->width; i++ ) { + if ( *fb++ != *lf++ ) { + strncpy( text, pd->framebuf + offset, pd->width ); + pd->lcd->settext( pd->lcd, line, 0, text ); + memcpy( pd->lstframe + offset, pd->framebuf + offset, pd->width ); + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: flush wrote line %d (%s)\n", line + 1, text ); + + break; + } + } + } + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: flush complete\n\t(%s)\n\t(%s)\n", pd->framebuf, pd->lstframe ); +} + +MODULE_EXPORT void picoLCD_string( Driver *drvthis, int x, int y, char *str ) { + PrivateData *pd = drvthis->private_data; + char *dest; + int len; + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: string start (%s)\n", str ); + + if ( y < 1 || y > pd->height ) + return; + if ( x < 1 || x > pd->width ) + return; + + len = strlen( str ); + if ( len + x > pd->width ) { + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: string overlength (>%d). Start: %d Length: %d (%s)\n", pd->width, x, len ,str ); + + len = pd->width - x; /* Copy what we can */ + } + + x--; y--; /* Convert 1-based to 0-based */ + dest = pd->framebuf + ( y * pd->width + x ); + memcpy( dest, str, len * sizeof(char) ); + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: string complete (%s)\n", str ); +} + +MODULE_EXPORT void picoLCD_chr( Driver *drvthis, int x, int y, char chr ) { + PrivateData *pd = drvthis->private_data; + char *dest; + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: chr start (%c)\n", chr ); + + if ( y < 1 || y > pd->height ) + return; + if ( x < 1 || x > pd->width ) + return; + + x--; y--; /* Convert 1-based to 0-based */ + dest = pd->framebuf + ( y * pd->width + x ); + memcpy( dest, &chr, sizeof(char) ); + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: chr complete (%c)\n", chr ); +} + +/* lcd_logical_driver Essential input functions */ + +MODULE_EXPORT char *picoLCD_get_key( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + lcd_packet *keydata; + char *keystr; + int keys_read = 0; + int key_pass = 0; + int two_keys = 0; + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key start (timeout %d)\n", pd->key_timeout ); + + keydata = malloc( sizeof( lcd_packet ) ); + + while ( ! keys_read ) { + get_key_event( pd->lcd, keydata, pd->key_timeout ); + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key got an event\n" ); + + if ( keydata->type == IN_REPORT_KEY_STATE ) { + if ( ! keydata->data[1] && key_pass ) { + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key got all clear\n" ); + /* Got a <0, 0> key-up event after reading a valid key press event */ + keys_read++; /* All clear */ + } else if ( ! keydata->data[2] && ! two_keys ) { + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key got one key\n" ); + /* We got one key (but not after a two key event and before and all clear) */ + keystr = pd->key_matrix[keydata->data[1]]; + } else { + /* We got two keys */ + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key got two keys\n" ); + two_keys++; + sprintf( keystr, "%s+%s", pd->key_matrix[keydata->data[1]], pd->key_matrix[keydata->data[2]] ); + } + + key_pass++; /* This hack allows us to deal with receiving left over <0,0> first */ + } else { + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key got non-key data or timeout\n" ); + /* We got IR or otherwise bad data */ + return NULL; + } + + } + + free( keydata ); + + if ( DEBUG_PICO ) + fprintf( stderr, "picolcd: get_key complete (%s)\n", keystr ); + + if ( ! strlen( keystr ) ) + return NULL; + + return keystr; + +/* + * Due to how key events are reported, we need to keep reading key presses + * until we get the all clear (all keys up) event. + * + * Key events come back in such a way to report up to two simultanious keys + * pressed. The highest numbered key always comes back as the first key and + * the lower numbered key follows. If only one key was pressed, the second + * key is 0. I will refer to a key event as: . + * + * Key ID numbers: + * 0 = (no key) + * 1 = + (plus) + * 2 = - (minus) + * 3 = F1 + * 4 = F2 + * 5 = F3 + * 6 = F4 + * 7 = F5 + * 8 = Left + * 9 = Right + * 10 = Up + * 11 = Down + * 12 = Enter + * + * The picoLCD also sends key-up events. + * + * On a single key press, the return is . The key-up event is a + * read that returns <0, 0> (all clear). On a dual key press, if one key is + * released later than the other key, the first key-up event is + * . This will be followed by a final "all clear" key-up + * <0, 0>. If both keys are release simultaniously, then after , + * you will receive <0, 0>. If the keys are pressed down in a staggard + * fashion, you will receive followed by followed by + * key-up events as already detailed. + * + * What this means is that we need to keep reading key presses until we get + * the <0, 0> all clear. + */ + +} + +/* lcd_logical_driver Extended output functions */ + +/* lcd_logical_driver User-defined character functions */ + +/* lcd_logical_driver Hardware functions */ +/*MODULE_EXPORT int picoLCD_get_contrast( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + +}*/ + +MODULE_EXPORT int picoLCD_set_contrast( Driver *drvthis, int promille ) { + PrivateData *pd = drvthis->private_data; + int inv; /* The hardware seems to go dark on higher values, so we turn it around */ + + if ( promille <= 1000 && promille > 0 ) { + inv = 1000 - promille; + pd->lcd->contrast( pd->lcd, ( int ) ( inv / 1000 * 40 ) ); + return 0; + } else if ( promille > 1000 ) { + pd->lcd->contrast( pd->lcd, 0 ); + return 0; + } else if ( promille <= 0 ) { + pd->lcd->contrast( pd->lcd, 40 ); + return 0; + } else { + return -1; + } +} + +/*MODULE_EXPORT int picoLCD_get_brightness( Driver *drvthis, int state ) { + PrivateData *pd = drvthis->private_data; + +}*/ + +/*MODULE_EXPORT int picoLCD_set_brightness( Driver *drvthis, int state, int promille ) { + PrivateData *pd = drvthis->private_data; + +}*/ + +MODULE_EXPORT void picoLCD_backlight( Driver *drvthis, int state ) { + PrivateData *pd = drvthis->private_data; + + if ( state == 0 ) { + pd->lcd->backlight( pd->lcd, state ); + set_key_lights( pd->lcd, pd->key_light, state ); + return; + } + + if ( state == 1 ) { + pd->lcd->backlight( pd->lcd, state ); + if ( pd->keylights ) + set_key_lights( pd->lcd, pd->key_light, state ); + return; + } + + return; +} + +/*MODULE_EXPORT int picoLCD_output( Driver *drvthis, int state ) { + PrivateData *pd = drvthis->private_data; + +}*/ + +/* lcd_logical_driver Informational functions */ +MODULE_EXPORT char *picoLCD_get_info( Driver *drvthis ) { + PrivateData *pd = drvthis->private_data; + + return pd->info; +} + +/* Private functions */ +void get_key_event ( usblcd_operations *self, lcd_packet *packet, int timeout ) { + int ret; + + memset( packet->data, 0, 255 ); + packet->type = 0; + ret = usb_interrupt_read( self->hid->hiddev->handle, USB_ENDPOINT_IN + 1, packet->data, _USBLCD_MAX_DATA_LEN, timeout ); + if ( ret > 0 ) { + switch ( packet->data[0] ) { + case IN_REPORT_KEY_STATE: { + packet->type = IN_REPORT_KEY_STATE; + } break; + case IN_REPORT_IR_DATA: { + packet->type = IN_REPORT_IR_DATA; + } break; + default: { + packet->type = 0; + } + } + } +} + +void set_key_lights ( usblcd_operations *self, int keys[], int state ) { + if ( state ) { + /* Only LEDs we want on */ + if ( keys[0] ) + self->setled( self, 0, 1 ); + if ( keys[1] ) + self->setled( self, 1, 1 ); + if ( keys[2] ) + self->setled( self, 2, 1 ); + if ( keys[3] ) + self->setled( self, 3, 1 ); + if ( keys[4] ) + self->setled( self, 4, 1 ); + if ( keys[5] ) + self->setled( self, 5, 1 ); + } else { + /* All LEDs off */ + self->setled( self, 0, 0 ); + self->setled( self, 1, 0 ); + self->setled( self, 2, 0 ); + self->setled( self, 3, 0 ); + self->setled( self, 4, 0 ); + self->setled( self, 5, 0 ); + } +} diff --git a/server/drivers/picolcd.h b/server/drivers/picolcd.h new file mode 100644 index 0000000..2e91ce9 --- /dev/null +++ b/server/drivers/picolcd.h @@ -0,0 +1,56 @@ +/* + * Driver for picoLCD graphical displays + * Header file + * + * (c) 2007 NitroSecurity, Inc. + * Written by Gatewood Green or + * + * License: GPL (same as usblcd and lcdPROC) + * + * picoLCD: http://www.mini-box.com/picoLCD-20x2-OEM + * Can be purchased separately or preinstalled in units such as the + * M300 http://www.mini-box.com/Mini-Box-M300-LCD + * + * See picolcd.c for full details + * + */ + +#ifndef PICOLCD_H +#define PCIOLCD_H + +#include "lcd.h" + +typedef struct _lcd_packet lcd_packet; +struct _lcd_packet { + unsigned char data[255]; + unsigned int type; +}; + +MODULE_EXPORT int picoLCD_init ( Driver *drvthis ); +MODULE_EXPORT void picoLCD_close ( Driver *drvthis ); +MODULE_EXPORT int picoLCD_width ( Driver *drvthis ); +MODULE_EXPORT int picoLCD_height ( Driver *drvthis ); +MODULE_EXPORT void picoLCD_clear ( Driver *drvthis ); +MODULE_EXPORT void picoLCD_flush ( Driver *drvthis ); +MODULE_EXPORT void picoLCD_string ( Driver *drvthis, int x, int y, char *str ); +MODULE_EXPORT void picoLCD_chr ( Driver *drvthis, int x, int y, char c ); + +MODULE_EXPORT char *picoLCD_get_key ( Driver *drvthis ); + +//MODULE_EXPORT void picoLCD_vbar ( Driver *drvthis, int x, int y, int len, int promille, int options ); +//MODULE_EXPORT void picoLCD_hbar ( Driver *drvthis, int x, int y, int len, int promille, int options ); +//MODULE_EXPORT void picoLCD_num ( Driver *drvthis, int x, int y, int num ); +//MODULE_EXPORT void picoLCD_heartbeat ( Driver *drvthis, int state ); +//MODULE_EXPORT void picoLCD_icon ( Driver *drvthis, int x, int y, int icon ); +//MODULE_EXPORT void picoLCD_cursor ( Driver *drvthis, int x, int y, int type ); + +//MODULE_EXPORT int picoLCD_get_contrast ( Driver *drvthis ); +MODULE_EXPORT int picoLCD_set_contrast ( Driver *drvthis, int promille ); +//MODULE_EXPORT int picoLCD_get_brightness ( Driver *drvthis, int state ); +//MODULE_EXPORT int picoLCD_set_brightness ( Driver *drvthis, int state, int promille ); +MODULE_EXPORT void picoLCD_backlight ( Driver *drvthis, int promille ); +//MODULE_EXPORT void picoLCD_output ( Driver *drvthis, int state ); + +MODULE_EXPORT char *picoLCD_get_info ( Driver *drvthis ); + +#endif