[Lcdproc] Mini-Box.com picoLCD (M300) LCD driver
Gatewood Green
woody@nitrosecurity.com
Thu Mar 1 19:24:02 2007
This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enig6960741B81A7F841F99764F4
Content-Type: multipart/mixed;
boundary="------------060505070305030803050501"
This is a multi-part message in MIME format.
--------------060505070305030803050501
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Attached is a patch to support to the Mini-Box.com USB LCD (picoLCD) as
shipped in the M300.
http://www.mini-box.com/picoLCD-20x2-OEM
http://www.mini-box.com/Mini-Box-M300-LCD
Comments and feedback welcome.
Thanks,
Woody
--=20
-----------------------------------------------------------------
Gatewood Green Software Engineer/System Admin
Email: woody@nitrosecurity.com
http://www.nitrosecurity.com/ NitroSecurity
-----------------------------------------------------------------
Imagine, if you will, a world in which there are no hypothetical
situations...
--------------060505070305030803050501
Content-Type: text/plain;
name="lcdproc-picolcd.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline;
filename="lcdproc-picolcd.patch"
diff -uNrp lcdproc-0.5-orig/LCDd.conf lcdproc-0.5-picolcd/LCDd.conf
--- lcdproc-0.5-orig/LCDd.conf 2007-02-23 13:45:24.000000000 -0700
+++ lcdproc-0.5-picolcd/LCDd.conf 2007-02-28 13:43:58.000000000 -0700
@@ -40,6 +40,7 @@ Driver=3DCFontz633
#Driver=3DCwLnx
#Driver=3Dglcdlib
#Driver=3Dimon
+#Driver=3Dpicolcd
=20
# Tells the driver to bind to the given interface
Bind=3D127.0.0.1
@@ -497,6 +498,38 @@ keypad_test_mode=3Dno
=20
=20
=20
+## Mini-box.com picoLCD (usblcd) driver ##
+[picolcd]
+# This is for the Mini-Box.com usblcd device that ships with the M300. =
It can=20
+# also be purchased separately but this driver has only been tested on t=
he M300=20
+# setup.
+
+# KeyTimeout is the time that LCDd spends waiting for a key press before=
cycling=20
+# through other duties. Higher values make LCDd use less CPU time and m=
ake=20
+# key presses more detectable. Lower values make LCDd more responsive b=
ut a=20
+# little prone to missing key presses. 500 (.5 second) is the default a=
nd a
+# balanced value.
+KeyTimeout=3D500
+
+# Contrast: 0 - 1000. 0 seems to work best and is the default.
+Contrast=3D0
+
+# Light the keys? 1 (on) / 0 (off). Default is 1 (on).
+Keylights=3D1
+
+# If Keylights =3D 1, the you can unlight specific keys below: 1 (on) / =
0 (off)
+# Key0 is the directional pad. Key1 - Key5 correspond to the F1 - F5 ke=
ys. =20
+# There is no LED for the +/- keys. This is a handy way to indicate to =
users=20
+# which keys are disabled. Defaults are 1 (on).
+Key0Light=3D1
+Key1Light=3D1
+Key2Light=3D1
+Key3Light=3D1
+Key4Light=3D1
+Key5Light=3D1
+
+
+
## Seiko Epson 1330 driver ##
[sed1330]
=20
diff -uNrp lcdproc-0.5-orig/acinclude.m4 lcdproc-0.5-picolcd/acinclude.m4=
--- lcdproc-0.5-orig/acinclude.m4 2005-07-04 01:00:33.000000000 -0600
+++ lcdproc-0.5-picolcd/acinclude.m4 2007-02-27 10:49:51.000000000 -0700
@@ -9,12 +9,13 @@ AC_ARG_ENABLE(drivers,
[ hd44780,joy,irman,lirc,bayrad,glk,mtc_s16209x]
[ stv5730,sed1330,sed1520,svga,lcdm001,t6963]
[ lcterm,icp_a106,ms6931,iowarrior,glcdlib,imon]
+ [ picolcd]
[ \"all\" compiles all drivers],
drivers=3D"$enableval",
drivers=3D[lcdm001,mtxorb,cfontz,cfontz633,curses,cwlnx,text,lb216,ba=
yrad,glk])
=20
if test "$drivers" =3D "all"; then
- drivers=3D[mtxorb,cfontz,cfontz633,curses,cwlnx,text,lb216,mtc_s16209x,=
hd44780,joy,irman,lirc,bayrad,glk,stv5730,sed1330,sed1520,svga,lcdm001,t6=
963,lcterm,icp_a106,ms6931,iowarrior,glcdlib,imon]
+ drivers=3D[mtxorb,cfontz,cfontz633,curses,cwlnx,text,lb216,mtc_s16209x,=
hd44780,joy,irman,lirc,bayrad,glk,stv5730,sed1330,sed1520,svga,lcdm001,t6=
963,lcterm,icp_a106,ms6931,iowarrior,glcdlib,imon,picolcd]
fi
=20
drivers=3D`echo $drivers | sed 's/,/ /g'`
@@ -256,6 +257,23 @@ dnl else
DRIVERS=3D"$DRIVERS imon${SO}"
actdrivers=3D["$actdrivers imon"]
;; =09
+ picolcd)
+ AC_CHECK_HEADERS([usblcd.h],[
+ AC_CHECK_LIB(usblcd, main,[
+ LIBUSBLCD=3D"-lusblcd"
+ DRIVERS=3D"$DRIVERS picolcd${SO}"
+ actdrivers=3D["$actdrivers picolcd"]
+ ],[
+dnl else
+ AC_MSG_WARN([The picolcd driver needs the usblcd library])
+ ],
+ [-lusblcd]
+ )
+ ],[
+dnl else =09
+ AC_MSG_WARN([The picolcd driver needs widgets.h, usblcd.h and usblcd=
_util.h from the usblcd package])
+ ]) =09
+ ;; =09
*)
AC_MSG_ERROR([Unknown driver $driver])
;;
@@ -272,6 +290,7 @@ AC_SUBST(LIBSVGA)
AC_SUBST(DRIVERS)
AC_SUBST(HD44780_DRIVERS)
AC_SUBST(LIBGLCD)
+AC_SUBST(LIBUSBLCD)
])
=20
=20
diff -uNrp lcdproc-0.5-orig/docs/LCDd.8 lcdproc-0.5-picolcd/docs/LCDd.8
--- lcdproc-0.5-orig/docs/LCDd.8 2005-05-30 01:00:19.000000000 -0600
+++ lcdproc-0.5-picolcd/docs/LCDd.8 2007-03-01 11:56:40.000000000 -0700
@@ -107,6 +107,9 @@ LB216 LCD display
.B lcdm001 (or LCDM001)
kernelconcepts.de 20x4 serial LCD displays
.TP
+.B picolcd
+Mini-box.com USB LCD (picoLCD 20x2)
+.TP
.B text
Standard "hard-copy" text display
.TP
diff -uNrp lcdproc-0.5-orig/docs/lcdproc-user/drivers/picolcd.docbook lcd=
proc-0.5-picolcd/docs/lcdproc-user/drivers/picolcd.docbook
--- lcdproc-0.5-orig/docs/lcdproc-user/drivers/picolcd.docbook 1969-12-31=
17:00:00.000000000 -0700
+++ lcdproc-0.5-picolcd/docs/lcdproc-user/drivers/picolcd.docbook 2007-03=
-01 11:52:56.000000000 -0700
@@ -0,0 +1,139 @@
+<sect1 id=3D"picolcd">
+ <title>The Mini-Box USB LCD (picoLCD 20x2) Driver (picolcd)</title>
+
+ <para>
+ This section covers the installation and use of the Mini-Box USB LCD (=
picoLCD=20
+ 20x2) display.
+ </para>
+ <para>
+ The picoLCD page indicates that the device can be connected via I2C or=
USART. =20
+ This lcdproc driver, however, is limited to the USB connected model.=20
+ </para>
+ <sect2 id=3D"picolcd-setup">
+ <title>Setting up the picoLCD</title>
+
+ <para>
+ The picoLCD device as used by this driver is USB connected and may be=
purchased=20
+ with an internal USB header connector (5-pin to 5-pin) or an external=
cable=20
+ (Type-A to 5-pin). See: http://www.mini-box.com/picoLCD-20x2-OEM. I=
t may also
+ come pre-installed on systems like the Mini-Box M300:=20
+ http://www.mini-box.com/Mini-Box-M300-LCD.
+ </para>
+ <para>
+ Using the USB LCD with this driver requires the usblcd library from M=
ini-box.com
+ (avaiable at http://www.mini-box.com/picoLCD-20x2-OEM). The usblcd l=
ibrary=20
+ requires libusb and libhcd. Your distribution may or may not already=
provide=20
+ these libraries. The only kernel driver required is the USB host con=
troller=20
+ driver (uhci_hcd on the M300) required to fire up the usb bus to whic=
h the LCD is=20
+ attached.
+ </para>
+ <para>
+ Lastly, the usbfs file system must be mounted on /proc/bus/usb.
+ <code>mount -t usbfs usbfs /proc/bus/usb</code>
+ </para>
+ <para>
+ Once connected and with libusblcd, libusb and libhid installed, testi=
ng the USB LCD=20
+ can be done with the "usblcd" program that comes with the usblcd libr=
ary. You can=20
+ also change the USB LCD's initial display (what it shows when you ini=
tialize the=20
+ device) by using the usblcd binary's "splash" command.
+ </para>
+ <para>
+ To use the picolcd with lcdproc, add picolcd to the lcdproc configure=
drivers option=20
+ (or use all) and then start LCDd with the "-d picolcd" option. The d=
river has=20
+ sane default options and the options that are user configurable are l=
imited to mostly=20
+ simple items, like contrast and which keys to lights up.
+ </para>
+ </sect2>
+ <sect2 id=3D"picolcd-options">
+ <para>
+ Contrast: 0-1000. 0 is visible, and 1000 is not on my M300. Default=
is 0. =09
+ </para>
+ <para>
+ Keylights: 0/1. 0 turns off the key LEDs and 1 turns them on. Defau=
lt is 1. =09
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ Key0Light: if Keylights is set to 1, you can disable the directional =
pad LED by=20
+ setting this value to 0. Default is 1.
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ Key1Light: if Keylights is set to 1, you can disable the F1 LED by se=
tting this value=20
+ to 0. Default is 1.
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ Key2Light: if Keylights is set to 1, you can disable the F2 LED by se=
tting this value=20
+ to 0. Default is 1.
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ Key3Light: if Keylights is set to 1, you can disable the F3 LED by se=
tting this value=20
+ to 0. Default is 1.
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ Key4Light: if Keylights is set to 1, you can disable the F4 LED by se=
tting this value=20
+ to 0. Default is 1.
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ Key5Light: if Keylights is set to 1, you can disable the F5 LED by se=
tting this value=20
+ to 0. Default is 1.
+ </para>
+ </sect2>
+ <sect2>
+ <para>
+ KeyTimeout: (Advanced) This value controls how long LCDd waits for a =
key press when=20
+ get_key is called. The value represents microseconds and the default=
is 500 or .5=20
+ seconds. Lowering this value will make LCDd more responsive but also=
causes LCDd to use=20
+ more CPU time and, as the timeout grows shorter, key presses become h=
arder to detect. =20
+ Larger values make key presses more reliable if somewhat slow to take=
effect.
+ </para>
+ </sect2>
+ <sect2 id=3D"picolcd-status">
+ <title>picolcd driver status</title>
+
+ <para>
+ The lcdproc picolcd driver relies upon Mini-Box's usblcd library to s=
etup the USB/HID=20
+ interface. Unfortunately the usblcd library is very thin and tends t=
o put function=20
+ results on stdout/stderr instead of in return values. They (Mini-Box=
) really had=20
+ scripting interfaces in mind.
+ </para>
+ <para>
+ The primary example of this is that I had to write a replacement (get=
_key_events) for=20
+ usblcd's read_events so that I could get the key presses back to the =
calling function=20
+ instead of on stdout. usblcd also has a large number of function she=
lls for which no=20
+ code exists yet. I am not an expert on HID and USB coding, but if an=
d as time permits=20
+ and hardware is available I will try and improve this drivers access =
to the hardware in=20
+ order to get back data (get_contrast for example) and to potentially =
drive multiple=20
+ pcioLCDs at once (or pick the one we want out of many).
+ </para>
+ <para>
+ To sum up, this driver right now stabs and hopes since response data =
is lacking.
+ </para>
+ <para>
+ The hardware also reports key-up events. Normally this would be of n=
o issue (they are=20
+ usually a 0 or 'no key') except that when keys are used in combonatio=
n, the key-up=20
+ event may actually come back as multiple events depending on how the =
user released the=20
+ keys. If the key-up event for a multiple key press comes back as two=
events, the first=20
+ up event will actually look like a new key press. The algorithm in g=
et_key tries to=20
+ deal with this in a sane way and toss out all key-up events for now. =
The hardware is=20
+ touchy and both combo key-down and key-up actions may be reported as =
mutiple events if=20
+ the user is more than a tenth of a second (maybe less?) off in motion=
s.
+ </para>
+ </sect2>
+ <sect2 id=3D"picolcd-copy">
+ <title>Copyright</title>
+ <para>
+ The lcdproc picolcd driver was written by Gatewood Green (woody@nitro=
security.com)=20
+ or (woody@linif.org) and paid for by NitroSecurity, Inc (nitrosecurit=
y.com).
+ </para>
+ </sect2>
+</sect1>
diff -uNrp lcdproc-0.5-orig/docs/lcdproc-user/drivers.docbook lcdproc-0.5=
-picolcd/docs/lcdproc-user/drivers.docbook
--- lcdproc-0.5-orig/docs/lcdproc-user/drivers.docbook 2002-10-25 19:45:2=
0.000000000 -0600
+++ lcdproc-0.5-picolcd/docs/lcdproc-user/drivers.docbook 2007-03-01 10:1=
7:36.000000000 -0700
@@ -12,5 +12,6 @@ well as the configuration of LCDd.
&ppttrouble;
&mtxorb;
&lircin;
+&picolcd;
=20
</chapter>
diff -uNrp lcdproc-0.5-orig/server/drivers/Makefile.am lcdproc-0.5-picolc=
d/server/drivers/Makefile.am
--- lcdproc-0.5-orig/server/drivers/Makefile.am 2005-06-05 01:00:25.00000=
0000 -0600
+++ lcdproc-0.5-picolcd/server/drivers/Makefile.am 2007-02-27 09:57:51.00=
0000000 -0700
@@ -18,7 +18,7 @@ AM_LDFLAGS =3D @LDSHARED@
LIBS =3D
=20
pkglib_PROGRAMS =3D @DRIVERS@
-EXTRA_PROGRAMS =3D bayrad CFontz CFontz633 curses CwLnx glk hd44780 irma=
n icp_a106 joy lb216 mtc_s16209x lcdm001 lcterm lirc MtxOrb sed1330 sed15=
20 stv5730 svga t6963 text wirz_sli ms6931 IOWarrior glcdlib imon
+EXTRA_PROGRAMS =3D bayrad CFontz CFontz633 curses CwLnx glk hd44780 irma=
n icp_a106 joy lb216 mtc_s16209x lcdm001 lcterm lirc MtxOrb sed1330 sed15=
20 stv5730 svga t6963 text wirz_sli ms6931 IOWarrior glcdlib imon picolcd=
noinst_LIBRARIES =3D libLCD.a
=20
IOWarrior_CFLAGS =3D @libusb_cflags@
@@ -40,6 +40,7 @@ svga_LDADD =3D @LIBSVGA@
t6963_LDADD =3D libLCD.a
glcdlib_LDADD =3D libLCD.a @LIBGLCD@
imon_LDADD =3D libLCD.a
+picolcd_LDADD =3D libLCD.a @LIBUSBLCD@
=20
libLCD_a_SOURCES =3D lcd_lib.h lcd_lib.c
=20
@@ -71,5 +72,6 @@ wirz_sli_SOURCES =3D lcd.h wirz-sli.h wi
ms6931_SOURCES =3D lcd.h ms6931.h ms6931.c report.h
glcdlib_SOURCES =3D lcd.h glcdlib.h glcdlib.c report.h
imon_SOURCES =3D lcd.h imon.h imon.c report.h
+picolcd_SOURCES =3D lcd.h picolcd.h picolcd.c report.h
=20
INCLUDES =3D -I$(top_srcdir)
diff -uNrp lcdproc-0.5-orig/server/drivers/picolcd.c lcdproc-0.5-picolcd/=
server/drivers/picolcd.c
--- lcdproc-0.5-orig/server/drivers/picolcd.c 1969-12-31 17:00:00.0000000=
00 -0700
+++ lcdproc-0.5-picolcd/server/drivers/picolcd.c 2007-03-01 10:08:39.0000=
00000 -0700
@@ -0,0 +1,518 @@
+/*
+ * picoLCD driver for lcdPROC
+ *
+ * (c) 2007 NitroSecurity, Inc.
+ * Written by Gatewood Green <woody@nitrosecurity.com> or <woody@linif.o=
rg>
+ *
+ * License: GPL (same as usblcd and lcdPROC)
+ *
+ * picoLCD: http://www.mini-box.com/picoLCD-20x2-OEM =20
+ * Can be purchased separately or preinstalled in units such as the=20
+ * M300 http://www.mini-box.com/Mini-Box-M300-LCD
+ *
+ * This driver (key lables and arrangement) is based on the M300 impleme=
ntation=20
+ * 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 w=
ith the=20
+ * Linux usblcd module which does NOT support this device). The usblcd =
library=20
+ * rides atop libusb and libhid (both of which are required for this dri=
ver to=20
+ * operate).
+ *
+ * libusb: http://libusb.sf.net
+ * libhid: http://libhid.alioth.debian.org
+ * usblcd: http://www.mini-box.com/picoLCD-20x2-OEM
+ *=20
+ * The usblcd library is very haphazardly written and directly writes to=
=20
+ * stdout and stderr instead of returning the result for most functions =
+ * (including read_events). Eventually it would be a good idea to elimi=
nate=20
+ * the need for usblcd and drive the hardware via libusb and libhid dire=
ctly. =20
+ * Such a conversion has the opportunity to provide meaningful return va=
lues=20
+ * for all fucntions (instead of stab and hope) and allow for use of mul=
tiple=20
+ * picoLCD devices.
+ *
+ * Due to the way libusblcd's read_events prints keys to stderr instead =
of=20
+ * returning a struct or some such, you will find my own get_key_events =
below.
+ *
+ * ### WARNING ###: libusblcd.so sets a handler for SIGTERM. Because mo=
st=20
+ * applications would set up their signal handling early on (before call=
ing=20
+ * new_usblcd_operations()), this can result in a condition that will pr=
event
+ * a handler your application installed from executing. If your handler=
was=20
+ * responsible for cleaning up logs, syncing, etc, it can result in lost=
data.=20
+ *=20
+ */
+
+/* lcdPROC includes */
+#include "lcd.h"
+#include "picolcd.h"
+#include "report.h"
+
+/* These three includes are the Mini-box.com libusblcd (usblcd) and comp=
any. */
+#include <usblcd.h>
+#include <widgets.h>
+#include <usblcd_util.h>
+
+/* Various odds and ends */
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/* 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 0 /* 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] =3D {
+ 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 t=
imeout );
+void set_key_lights ( usblcd_operations *self, int keys[], int state );
+
+/* lcd_logical_driver Variables */
+MODULE_EXPORT char *api_version =3D API_VERSION;
+MODULE_EXPORT int stay_in_foreground =3D 0;
+MODULE_EXPORT int supports_multiple =3D 1;
+MODULE_EXPORT char *symbol_prefix =3D "picoLCD_";
+
+/* lcd_logical_driver Manditory functions */
+MODULE_EXPORT int picoLCD_init( Driver *drvthis ) {
+ PrivateData *pd;
+ int x;
+
+ pd =3D ( PrivateData * ) malloc( sizeof( PrivateData ) );
+
+ if ( ! pd )
+ return -1;
+
+ if ( drvthis->store_private_ptr( drvthis, pd ) )
+ return -1;
+
+ pd->lcd =3D new_usblcd_operations();
+ pd->lcd->init( pd->lcd );
+ pd->width =3D 20; /* hard coded (mfg spec) */
+ pd->height =3D 2; /* hard coded (mfg spec) */
+ pd->info =3D "picoLCD: Supports the LCD as installed on the M300 (http:=
//www.mini-box.com/Mini-Box-M300-LCD) ";
+
+ for ( x =3D 0; x < KEYPAD_LIGHTS; x++ )
+ pd->key_light[x] =3D 1; /* individual lights on */
+
+ pd->contrast =3D drvthis->config_get_int( drvthis->name, "Contrast"=
, 0, DEFAULT_CONTRAST );
+ pd->backlight =3D drvthis->config_get_int( drvthis->name, "BackLight=
", 0, DEFAULT_BACKLIGHT );
+ pd->keylights =3D drvthis->config_get_int( drvthis->name, "KeyLights=
", 0, DEFAULT_KEYLIGHTS ); /* key lights with LCD Backlight? */
+ pd->key_timeout =3D drvthis->config_get_int( drvthis->name, "KeyTimeou=
t", 0, DEFAULT_TIMEOUT );
+
+ /* These allow individual lights to be disabled */
+ pd->key_light[0] =3D drvthis->config_get_int( drvthis->name, "Key0Light=
", 0, 1 ); /* Directional PAD */
+ pd->key_light[1] =3D drvthis->config_get_int( drvthis->name, "Key1Light=
", 0, 1 ); /* F1 */
+ pd->key_light[2] =3D drvthis->config_get_int( drvthis->name, "Key2Light=
", 0, 1 ); /* F2 */
+ pd->key_light[3] =3D drvthis->config_get_int( drvthis->name, "Key3Light=
", 0, 1 ); /* F3 */
+ pd->key_light[4] =3D drvthis->config_get_int( drvthis->name, "Key4Light=
", 0, 1 ); /* F4 */
+ pd->key_light[5] =3D drvthis->config_get_int( drvthis->name, "Key5Light=
", 0, 1 ); /* F5 */
+
+ for ( x =3D 0; x < KEYPAD_MAX; x++ )
+ pd->key_matrix[x] =3D keymap[x];
+
+ pd->framebuf =3D ( unsigned char * ) malloc( pd->width * pd->height + 1=
);
+ if ( pd->framebuf =3D=3D 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] =3D 0;
+
+ pd->lstframe =3D ( unsigned char * ) malloc( pd->width * pd->height + 1=
);
+ if ( pd->lstframe =3D=3D 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] =3D 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 =3D drvthis->private_data;
+
+ pd->lcd->close( pd->lcd ); /* This actually does not do anything in usb=
lcd (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 =3D drvthis->private_data;
+
+ return pd->width;
+}
+
+MODULE_EXPORT int picoLCD_height( Driver *drvthis ) {
+ PrivateData *pd =3D drvthis->private_data;
+
+ return pd->height;
+}
+
+MODULE_EXPORT void picoLCD_clear( Driver *drvthis ) {
+ PrivateData *pd =3D 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 =3D drvthis->private_data;
+ unsigned char *fb =3D pd->framebuf;
+ unsigned char *lf =3D pd->lstframe;
+ static char text[48];
+ int i, line, offset;
+
+ if ( DEBUG_PICO )
+ fprintf( stderr, "picolcd: flush started\n" );
+
+ for ( line =3D 0; line < pd->height; line++ ) {=20
+ memset( text, 0, 48 );=20
+ offset =3D line * pd->width;
+ fb =3D pd->framebuf + offset;
+ lf =3D pd->lstframe + offset;
+
+ for ( i =3D 0; i < pd->width; i++ ) {
+ if ( *fb++ !=3D *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, t=
ext );
+
+ break;
+ }
+ }
+ }
+
+ if ( DEBUG_PICO )
+ fprintf( stderr, "picolcd: flush complete\n\t(%s)\n\t(%s)\n", pd->fram=
ebuf, pd->lstframe );
+}
+
+MODULE_EXPORT void picoLCD_string( Driver *drvthis, int x, int y, char *=
str ) {
+ PrivateData *pd =3D 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 =3D 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 =3D pd->width - x; /* Copy what we can */
+ }
+
+ x--; y--; /* Convert 1-based to 0-based */
+ dest =3D 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 =3D 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 =3D 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 =3D drvthis->private_data;
+ lcd_packet *keydata;
+ char *keystr;
+ int keys_read =3D 0;
+ int key_pass =3D 0;
+ int two_keys =3D 0;
+
+ if ( DEBUG_PICO )
+ fprintf( stderr, "picolcd: get_key start (timeout %d)\n", pd->key_time=
out );
+
+ keydata =3D 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 =3D=3D 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 =3D 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;
+
+/*=20
+ * Due to how key events are reported, we need to keep reading key press=
es=20
+ * until we get the all clear (all keys up) event.
+ *=20
+ * Key events come back in such a way to report up to two simultanious k=
eys=20
+ * pressed. The highest numbered key always comes back as the first key=
and=20
+ * the lower numbered key follows. If only one key was pressed, the sec=
ond=20
+ * key is 0. I will refer to a key event as: <high key, low key>.
+ *
+ * Key ID numbers:
+ * 0 =3D (no key)
+ * 1 =3D + (plus)
+ * 2 =3D - (minus)
+ * 3 =3D F1
+ * 4 =3D F2
+ * 5 =3D F3
+ * 6 =3D F4
+ * 7 =3D F5
+ * 8 =3D Left
+ * 9 =3D Right
+ * 10 =3D Up
+ * 11 =3D Down
+ * 12 =3D Enter
+ *=20
+ * The picoLCD also sends key-up events.
+ *
+ * On a single key press, the return is <keynum, 0>. The key-up event i=
s a=20
+ * read that returns <0, 0> (all clear). On a dual key press, if one ke=
y is=20
+ * released later than the other key, the first key-up event is=20
+ * <remainingkey, 0>. This will be followed by a final "all clear" key-=
up=20
+ * <0, 0>. If both keys are release simultaniously, then after <hk, lk>=
,=20
+ * you will receive <0, 0>. If the keys are pressed down in a staggard =
+ * fashion, you will receive <first key, 0> followed by <hk, lk> followe=
d by=20
+ * key-up events as already detailed.
+ *
+ * What this means is that we need to keep reading key presses until we =
get=20
+ * the <0, 0> all clear.
+ */
+=09
+}
+
+/* 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 =3D drvthis->private_data;
+
+}*/
+
+MODULE_EXPORT int picoLCD_set_contrast( Driver *drvthis, int promille )=
{
+ PrivateData *pd =3D drvthis->private_data;
+
+ if ( promille <=3D 1000 && promille > 0 ) {
+ pd->lcd->contrast( pd->lcd, ( int ) ( promille / 1000 * 40 ) );
+ return 0;
+ } else if ( promille > 1000 ) {
+ pd->lcd->contrast( pd->lcd, 40 );
+ return 0;
+ } else if ( promille <=3D 0 ) {
+ pd->lcd->contrast( pd->lcd, 0 );
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/*MODULE_EXPORT int picoLCD_get_brightness( Driver *drvthis, int state )=
{
+ PrivateData *pd =3D drvthis->private_data;
+
+}*/
+
+/*MODULE_EXPORT int picoLCD_set_brightness( Driver *drvthis, int state,=
int promille ) {
+ PrivateData *pd =3D drvthis->private_data;
+
+}*/
+
+MODULE_EXPORT void picoLCD_backlight( Driver *drvthis, int state ) {
+ PrivateData *pd =3D drvthis->private_data;
+
+ if ( state =3D=3D 0 ) {
+ pd->lcd->backlight( pd->lcd, state );
+ set_key_lights( pd->lcd, pd->key_light, state );
+ return;
+ }
+
+ if ( state =3D=3D 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 =3D drvthis->private_data;
+
+}*/
+
+/* lcd_logical_driver Informational functions */
+MODULE_EXPORT char *picoLCD_get_info( Driver *drvthis ) {
+ PrivateData *pd =3D drvthis->private_data;
+
+ return pd->info;
+}
+
+/* Private functions */
+void get_key_event ( usblcd_operations *self, lcd_packet *packet, int ti=
meout ) {
+ int ret;
+
+ memset( packet->data, 0, 255 );
+ packet->type =3D 0;
+ ret =3D 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 =3D IN_REPORT_KEY_STATE;
+ } break;
+ case IN_REPORT_IR_DATA: {
+ packet->type =3D IN_REPORT_IR_DATA;
+ } break;
+ default: {
+ packet->type =3D 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 -uNrp lcdproc-0.5-orig/server/drivers/picolcd.h lcdproc-0.5-picolcd/=
server/drivers/picolcd.h
--- lcdproc-0.5-orig/server/drivers/picolcd.h 1969-12-31 17:00:00.0000000=
00 -0700
+++ lcdproc-0.5-picolcd/server/drivers/picolcd.h 2007-02-28 11:19:01.0000=
00000 -0700
@@ -0,0 +1,56 @@
+/*
+ * Driver for picoLCD graphical displays
+ * Header file
+ *
+ * (c) 2007 NitroSecurity, Inc.
+ * Written by Gatewood Green <woody@nitrosecurity.com> or <woody@linif.o=
rg>
+ *
+ * License: GPL (same as usblcd and lcdPROC)
+ *
+ * picoLCD: http://www.mini-box.com/picoLCD-20x2-OEM =20
+ * Can be purchased separately or preinstalled in units such as the=20
+ * 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, ch=
ar *str );
+MODULE_EXPORT void picoLCD_chr ( Driver *drvthis, int x, int y, ch=
ar 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 promill=
e );
+//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 promill=
e );
+//MODULE_EXPORT void picoLCD_output ( Driver *drvthis, int state=
);
+
+MODULE_EXPORT char *picoLCD_get_info ( Driver *drvthis );
+
+#endif
--------------060505070305030803050501--
--------------enig6960741B81A7F841F99764F4
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFF5yhEHnsUla8nzK0RA8ivAJ9DxtM0sQbrs76viFz5N4Y0csaVBwCgrold
Cs3MVeFjqVNhsZhkj7x9Zeg=
=X/KW
-----END PGP SIGNATURE-----
--------------enig6960741B81A7F841F99764F4--