Author: pebender
Date: Wed Jan 21 16:08:43 2009
New Revision: 4298
Added:
trunk/gar-minimyth/script/system/lcdproc/files/lcdproc-0.5.2-picolcd_4x20.patch
Modified:
trunk/gar-minimyth/html/minimyth/document-changelog.txt
trunk/gar-minimyth/script/system/lcdproc/Makefile
trunk/gar-minimyth/script/system/lcdproc/checksums
Log:
Modified LCDproc
- Replaced the picolcd driver with the picolcd 4x20 driver from
<http://resources.mini-box.com/online/picolcd/4x20/lcdproc-picolcd20x4-0.5.2-cvs.tgz>.
This allows
- The driver to compile because it no longer depends on liblcdusb.
- Support for 4x20 displays.
- Support for LIRC.
- The driver has not be verified to work.
- The LIRC support has not been verified to work.
- The LIRC support has not been integrated into MiniMyth's init system.
Modified: trunk/gar-minimyth/html/minimyth/document-changelog.txt
==============================================================================
--- trunk/gar-minimyth/html/minimyth/document-changelog.txt (original)
+++ trunk/gar-minimyth/html/minimyth/document-changelog.txt Wed Jan 21
16:08:43 2009
@@ -1,7 +1,7 @@
MiniMyth Changelog
--------------------------------------------------------------------------------
-Changes since 63 (2009-01-19):
+Changes since 63 (2009-01-21):
Current MythTV versions
MythTV 0.20-softpad: version 0.20.2.softpad, release-0-20-fixes branch
svn 16082,
@@ -53,6 +53,17 @@
- This causes /sys/module/lirc_imon/parameters/is_lcd to no longer
be
available, but with autodetection is should no longer be needed.
- Enabled lirc_gpio.
+
+Modified LCDproc
+ - Replaced the picolcd driver with the picolcd 4x20 driver from
+
<http://resources.mini-box.com/online/picolcd/4x20/lcdproc-picolcd20x4-0.5.2-cvs.tgz>.
+ This allows
+ - The driver to compile because it no longer depends on liblcdusb.
+ - Support for 4x20 displays.
+ - Support for LIRC.
+ - The driver has not be verified to work.
+ - The LIRC support has not been verified to work.
+ - The LIRC support has not been integrated into MiniMyth's init system.
Modified init
- Added detection of i2c lirc devices.
Modified: trunk/gar-minimyth/script/system/lcdproc/Makefile
==============================================================================
--- trunk/gar-minimyth/script/system/lcdproc/Makefile (original)
+++ trunk/gar-minimyth/script/system/lcdproc/Makefile Wed Jan 21 16:08:43
2009
@@ -7,6 +7,7 @@
DISTFILES = $(DISTNAME).tar.gz
PATCHFILES =
PATCHFILES += $(DISTNAME)-irtrans.patch
+PATCHFILES += $(DISTNAME)-picolcd_4x20.patch
PATCHFILES += $(DISTNAME)-dm140_henlar_v0.2.patch
$(DISTNAME)-imonlcd_0.3_with_send_fix.patch
else
MASTER_SITES =
cvs://anonym...@$(GARNAME).cvs.sourceforge.net:/cvsroot/$(GARNAME)/
Modified: trunk/gar-minimyth/script/system/lcdproc/checksums
==============================================================================
--- trunk/gar-minimyth/script/system/lcdproc/checksums (original)
+++ trunk/gar-minimyth/script/system/lcdproc/checksums Wed Jan 21 16:08:43
2009
@@ -1,5 +1,6 @@
860f192d061d87dda6512b11b79daac2 download/lcdproc-0.5.2.tar.gz
67350a7cda81f03ca28d0d220e9e0805 download/lcdproc-0.5.2-irtrans.patch
+f3bdf7db112b96cc05d1959012bac347 download/lcdproc-0.5.2-picolcd_4x20.patch
a16c8ba13dafecf34dba9c79e203295e
download/lcdproc-0.5.2-dm140_henlar_v0.2.patch
72196e1f7f10150bf1baad8dc74a6fba
download/lcdproc-0.5.2-imonlcd_0.3_with_send_fix.patch
Added:
trunk/gar-minimyth/script/system/lcdproc/files/lcdproc-0.5.2-picolcd_4x20.patch
==============================================================================
--- (empty file)
+++
trunk/gar-minimyth/script/system/lcdproc/files/lcdproc-0.5.2-picolcd_4x20.patch
Wed Jan 21 16:08:43 2009
@@ -0,0 +1,1471 @@
+diff -Naur lcdproc-0.5.2-old/acinclude.m4 lcdproc-0.5.2-new/acinclude.m4
+--- lcdproc-0.5.2-old/acinclude.m4 2007-04-14 07:39:28.000000000 -0700
++++ lcdproc-0.5.2-new/acinclude.m4 2009-01-21 15:29:16.000000000 -0800
+@@ -277,21 +277,12 @@
+ 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])
+- ])
++ if test "$enable_libusb" = yes ; then
++ DRIVERS="$DRIVERS picolcd${SO}"
++ actdrivers=["$actdrivers picolcd"]
++ else
++ AC_MSG_WARN([The picolcd driver needs the
libusb library.])
++ fi
+ ;;
+ pyramid)
+ DRIVERS="$DRIVERS pyramid${SO}"
+diff -Naur lcdproc-0.5.2-old/server/drivers/picolcd.c
lcdproc-0.5.2-new/server/drivers/picolcd.c
+--- lcdproc-0.5.2-old/server/drivers/picolcd.c 2007-04-14
07:38:14.000000000 -0700
++++ lcdproc-0.5.2-new/server/drivers/picolcd.c 2009-01-21
15:28:04.000000000 -0800
+@@ -3,50 +3,31 @@
+ *
+ * (c) 2007 NitroSecurity, Inc.
+ * Written by Gatewood Green <[email protected]> or
<[email protected]>
+- * (c) 2007 Peter Marschall - adapted coding style and reporting to
LCDproc
+- *
++ * (c) 2007-2008 Peter Marschall - adapted coding style and reporting to
LCDproc
++ * (c) 2007 Mini-Box.com, Nicu Pavel <[email protected]>
++ * - removed libusblcd and hid dependency
++ * - added vbar, hbar, custom char, bignum support
++ * (c) 2008 Jack Cleaver - add LIRC connection
++ * (c) 2008 Mini-Box.com Nicu Pavel <[email protected]>
++ * - Added support for 4x20 picoLCD
+ * 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
++ * picoLCD 4x20: http://www.mini-box.com/PicoLCD-4X20-Sideshow
+ *
+ * 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).
++ * using libusb library.
+ *
+ * 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 <usb.h>
+ /* Debug mode: un-comment to turn on debugging messages in the server */
+ /* #define DEBUG 1 */
+
+@@ -56,63 +37,119 @@
+ # include "config.h"
+ #endif
+
+-/* These three includes are the Mini-box.com libusblcd (usblcd) and
company. */
+-#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>
+-
+-/* 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 */
+-
++#include <netdb.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++
++#define DEFAULT_CONTRAST 1000 /* Full */
++#define DEFAULT_BRIGHTNESS 255 /* Full */
++#define DEFAULT_BACKLIGHT 1 /* On */
++#define DEFAULT_KEYLIGHTS 1 /* On */
++#define DEFAULT_TIMEOUT 500 /* Half second */
++
++#define NUM_CCs 8 /* max. number of custom characters */
++
++typedef enum {
++ standard, /* only char 0 is used for heartbeat */
++ vbar, /* vertical bars */
++ hbar, /* horizontal bars */
++ custom, /* custom settings */
++ bignum, /* big numbers */
++ bigchar /* big characters */
++} CGmode;
+
+ /* PrivateData struct */
+ typedef struct pd {
+- usblcd_operations *lcd; // Reference to the LCD instance
++ usb_dev_handle *lcd;
+ int width;
+ int height;
++ int cellwidth;
++ int cellheight;
+ int key_timeout;
+ int contrast;
+ int backlight;
++ int brightness;
+ int keylights;
+ int key_light[KEYPAD_LIGHTS];
+- char *key_matrix[KEYPAD_MAX];
++ /* defineable characters */
++ CGmode ccmode;
+ char *info;
+ unsigned char *framebuf;
+ unsigned char *lstframe;
++ /* device info struct */
++ picolcd_device *device;
++ int IRenabled;
++ //For communicating with LIRC
++ int lircsock;
++ struct sockaddr_in lircserver;
++ /* IR transcode results */
++ unsigned char result[512];
++ int sync;
++ int preset_gap;
++ int gap;
+ } 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);
++static void picolcd_send(usb_dev_handle *lcd, unsigned char *data, int
size);
++/* Write function for 20x2 OEM displays */
++static void picolcd_20x2_write(usb_dev_handle *lcd, const int row, const
int col, const unsigned char *data);
++/* Write function for 20x4 desktop displays */
++static void picolcd_20x4_write(usb_dev_handle *lcd, const int row, const
int col, const unsigned char *data);
++/* Custom character define function for 20x2 OEM displays */
++static void picolcd_20x2_set_char (Driver *drvthis, int n, unsigned char
*dat);
++/* Custom character define function for 20x4 desktop displays */
++static void picolcd_20x4_set_char (Driver *drvthis, int n, unsigned char
*dat);
++static void get_key_event (usb_dev_handle *lcd, lcd_packet *packet, int
timeout);
++static void set_key_lights (usb_dev_handle *lcd, int keys[], int state);
++static int ir_transcode(Driver *drvthis, unsigned char *data, unsigned
int cbdata,
++ unsigned char *result, int
cbresult);
++
++picolcd_device picolcd_device_ids[] = {
++ {
++ .device_name = "picoLCD20x2",
++ .description = "Driver for picoLCD 20x2 OEM and picoLCD
found on M200/M300 cases",
++ .vendor_id = 0x04d8,
++ .device_id = 0x0002,
++ .bklight_max = 1,
++ .bklight_min = 0,
++ .contrast_max = 40,
++ .contrast_min = 0,
++ .width = 20,
++ .height = 2,
++ .write = picolcd_20x2_write,
++ .cchar = picolcd_20x2_set_char,
++ .keymap = {
NULL, "Plus", "Minus", "F1", "F2", "F3", "F4", "F5",
++ "Left","Right", "Up", "Down", "Enter" },
++ .initseq = {},
++ },
++ {
++ .device_name = "picoLCD20x4",
++ .description = "Driver for picoLCD 20x4 desktop LCD",
++ .vendor_id = 0x04d8,
++ .device_id = 0xc001,
++ .bklight_max = 100,
++ .bklight_min = 0,
++ .contrast_max = 1,
++ .contrast_min = 0,
++ .width = 20,
++ .height = 4,
++ .write = picolcd_20x4_write,
++ .cchar = picolcd_20x4_set_char,
++ .keymap = {
NULL, "Back", "F1", "F2", "F3", "Home", "Down",
++ "Enter", "Up", "", "", "", ""},
++ .initseq = { 0x94, 0x00, 0x07, 0x00, 0x32, 0x30,
0x00,0x32, 0x30, 0x00, 0x32,
++ 0x30, 0x00, 0x32, 0x38, 0x00, 0x32,
0x06, 0x00, 0x32, 0x0C, 0x07,
++ 0xD0, 0x01},
++ },
++ {}, /* End list */
++};
+
+ /* lcd_logical_driver Variables */
+ MODULE_EXPORT char *api_version = API_VERSION;
+@@ -120,229 +157,508 @@
+ MODULE_EXPORT int supports_multiple = 1;
+ MODULE_EXPORT char *symbol_prefix = "picoLCD_";
+
+-/* lcd_logical_driver Manditory functions */
++/* lcd_logical_driver mandatory functions */
+ MODULE_EXPORT int picoLCD_init(Driver *drvthis) {
+- PrivateData *pd;
++ PrivateData *p;
+ int x;
++ struct usb_bus *bus;
++ struct usb_device *dev;
++ const char *lirchost;
++ int lircport;
++ int id;
+
+- pd = (PrivateData *) malloc(sizeof(PrivateData));
+-
+- if (! pd)
++ p = (PrivateData *) malloc(sizeof(PrivateData));
++ if (p == NULL)
+ return -1;
+
+- if (drvthis->store_private_ptr(drvthis, pd))
++ if (drvthis->store_private_ptr(drvthis, p))
+ 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) ";
++ /* Try to find picolcd device */
++ usb_init();
++ usb_find_busses();
++ usb_find_devices();
++
++ p->lcd = NULL;
++ p->device = NULL;
++
++ for (id = 0; picolcd_device_ids[id].device_name; ++id) {
++ report(RPT_INFO, "Looking for device %s ",
picolcd_device_ids[id].device_name);
++ for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
++ for (dev = bus->devices; dev != NULL; dev = dev->next) {
++ if ((dev->descriptor.idVendor ==
picolcd_device_ids[id].vendor_id) &&
++ (dev->descriptor.idProduct ==
picolcd_device_ids[id].device_id)) {
++
++ report(RPT_INFO, "Found %s on bus %s
device %s",
picolcd_device_ids[id].device_name,
++ bus->dirname,
dev->filename);
++
++ p->lcd = usb_open(dev);
++ p->device = &picolcd_device_ids[id];
++ goto done;
++ }
++ }
++ }
++ }
++ done:
++
++ if (p->lcd != NULL) {
++ debug(RPT_DEBUG, "%s: opening device succeeded", drvthis->name);
++#ifdef LIBUSB_HAS_GET_DRIVER_NP
++ char driver[1024];
++ if (usb_get_driver_np(p->lcd, 0, driver, sizeof(driver))
== 0) {
++ report(RPT_WARNING, "Interface 0 already claimed
by '%s' detaching.", driver);
++#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
++ if ((usb_detach_kernel_driver_np(p->lcd, 0) < 0))
++ report(RPT_ERR, "%s: unable to detach %s
driver", driver);
++#endif
++ }
++#endif
++ if (usb_claim_interface(p->lcd, 0) < 0) {
++ report(RPT_ERR, "Cannot claim interface !", driver);
++ usb_close(p->lcd);
++ return -1;
++ }
++ usleep(100);
++ if (usb_set_altinterface(p->lcd, 0) < 0)
++ report(RPT_WARNING, "%s: unable to set alternate
configuration",
drvthis->name);
++ } else {
++ report(RPT_ERR, "%s: no device found", drvthis->name);
++ return -1;
++ }
++
++ /* if the device has a init sequence sent it to device */
++ picolcd_send(p->lcd, p->device->initseq, PICOLCD_MAX_DATA_LEN);
++
++ p->width = p->device->width;
++ p->height = p->device->height;
++ p->info = p->device->description;
++ p->cellwidth = LCD_DEFAULT_CELLWIDTH;
++ p->cellheight = LCD_DEFAULT_CELLHEIGHT;
++ p->ccmode = standard;
+
+ for (x = 0; x < KEYPAD_LIGHTS; x++)
+- pd->key_light[x] = 1; /* individual lights on */
++ p->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 );
++ p->contrast = drvthis->config_get_int( drvthis->name, "Contrast",
0, DEFAULT_CONTRAST );
++ p->brightness = drvthis->config_get_int(
drvthis->name, "Brightness", 0, DEFAULT_BRIGHTNESS );
++ p->backlight = drvthis->config_get_bool(drvthis->name, "BackLight",
0, DEFAULT_BACKLIGHT);
++ p->keylights = drvthis->config_get_bool(drvthis->name, "KeyLights",
0, DEFAULT_KEYLIGHTS); /* key lights with LCD Backlight? */
++ p->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__);
++ p->key_light[0] = drvthis->config_get_bool(drvthis->name, "Key0Light",
0, 1);
++ p->key_light[1] = drvthis->config_get_bool(drvthis->name, "Key1Light",
0, 1);
++ p->key_light[2] = drvthis->config_get_bool(drvthis->name, "Key2Light",
0, 1);
++ p->key_light[3] = drvthis->config_get_bool(drvthis->name, "Key3Light",
0, 1);
++ p->key_light[4] = drvthis->config_get_bool(drvthis->name, "Key4Light",
0, 1);
++ p->key_light[5] = drvthis->config_get_bool(drvthis->name, "Key5Light",
0, 1);
++ p->key_light[6] = drvthis->config_get_bool(drvthis->name, "Key6Light",
0, 1);
++ p->key_light[7] = drvthis->config_get_bool(drvthis->name, "Key7Light",
0, 1);
++
++ p->framebuf = (unsigned char *) malloc(p->width * p->height + 1);
++ if (p->framebuf == NULL) {
++ report(RPT_ERR, "%s: unable to create framebuf", drvthis->name);
+ return -1;
+ }
+- memset(pd->framebuf, ' ', pd->width * pd->height);
+- pd->framebuf[pd->width * pd->height] = 0;
++ memset(p->framebuf, ' ', p->width * p->height);
++ p->framebuf[p->width * p->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__);
++ p->lstframe = (unsigned char *) malloc(p->width * p->height + 1);
++ if (p->lstframe == NULL) {
++ report(RPT_ERR, "%s: unable to create lstframe", drvthis->name);
+ return -1;
+ }
+- memset(pd->lstframe, ' ', pd->width * pd->height);
+- pd->lstframe[pd->width * pd->height] = 0;
++ memset(p->lstframe, ' ', p->width * p->height);
++ p->lstframe[p->width * p->height] = '\0';
+
+- if (pd->backlight)
++ if (p->backlight)
+ picoLCD_backlight(drvthis, 1);
+- if (! pd->keylights)
+- set_key_lights(pd->lcd, pd->key_light, 0);
++ if (! p->keylights)
++ set_key_lights(p->lcd, p->key_light, 0);
+ else
+ picoLCD_backlight(drvthis, 0);
+
+- picoLCD_set_contrast(drvthis, pd->contrast);
++ picoLCD_set_contrast(drvthis, p->contrast);
++
++ lirchost = drvthis->config_get_string(drvthis->name, "LircHost",
0,
NULL);
++ lircport = drvthis->config_get_int(drvthis->name, "LircPort", 0,
DEFAULT_LIRCPORT);
++ p->sync = drvthis->config_get_int(drvthis->name, "LircSync", 0,
DEFAULT_SYNC_JIFFY);
++ p->preset_gap = drvthis->config_get_int(drvthis->name, "LircLength", 0,
DEFAULT_LENGTH_JIFFY);
++
++ p->IRenabled = (lirchost != NULL && *lirchost != '\0') ? 1 : 0;
++
++ if (p->IRenabled) {
++ /* Initialize communication with LIRC */
++ struct hostent *hostinfo = gethostbyname(lirchost);
++
++ if (hostinfo == NULL) {
++ report (RPT_ERR, "%s: unknown LIRC host %s",
drvthis->name, lirchost);
++ return -1;
++ }
++ if ((p->lircsock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) <
0) {
++ report(RPT_ERR, "%s: failed to create socket to send
data to LIRC",
drvthis->name);
++ return -1;
++ }
++
++ /* Construct the server sockaddr_in structure */
++ memset(&p->lircserver, 0, sizeof(p->lircserver));
/* Clear struct */
++ p->lircserver.sin_family = AF_INET;
/* Internet/IP */
++ p->lircserver.sin_addr = *(struct in_addr *) hostinfo->h_addr;
/* IP address */
++ p->lircserver.sin_port = htons(lircport);
/* server port */
++
++ report(RPT_INFO, "%s: IR events will be sent to LIRC on %s:%d,
with
sync=%d and length=%d",
++ drvthis->name, lirchost, lircport, p->sync,
p->preset_gap);
++ }
+
+- report(RPT_INFO, "picolcd: init complete\n", __FUNCTION__);
++ report(RPT_INFO, "%s: init complete", drvthis->name);
+
+ 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?) */
++MODULE_EXPORT void picoLCD_close(Driver *drvthis)
++{
++ PrivateData *p = drvthis->private_data;
+
+- debug(RPT_DEBUG, "picolcd: close complete\n");
++ usb_release_interface(p->lcd, 0);
++ usb_close(p->lcd);
++
++ debug(RPT_DEBUG, "%s: close complete", drvthis->name);
+ }
+
++
+ /* lcd_logical_driver Essential output functions */
+-MODULE_EXPORT int picoLCD_width(Driver *drvthis) {
+- PrivateData *pd = drvthis->private_data;
++MODULE_EXPORT int picoLCD_width(Driver *drvthis)
++{
++ PrivateData *p = drvthis->private_data;
+
+- return pd->width;
++ return p->width;
+ }
+
+-MODULE_EXPORT int picoLCD_height(Driver *drvthis) {
+- PrivateData *pd = drvthis->private_data;
+
+- return pd->height;
++MODULE_EXPORT int picoLCD_height(Driver *drvthis)
++{
++ PrivateData *p = drvthis->private_data;
++
++ return p->height;
+ }
+
+-MODULE_EXPORT void picoLCD_clear(Driver *drvthis) {
+- PrivateData *pd = drvthis->private_data;
+
+- memset(pd->framebuf, ' ', pd->width * pd->height);
++MODULE_EXPORT void picoLCD_clear(Driver *drvthis)
++{
++ PrivateData *p = drvthis->private_data;
+
+- debug(RPT_DEBUG, "picolcd: clear complete\n");
++ memset(p->framebuf, ' ', p->width * p->height);
++ p->ccmode = standard;
++
++ debug(RPT_DEBUG, "%s: clear complete", drvthis->name);
+ }
+
+-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];
++
++MODULE_EXPORT void picoLCD_flush(Driver *drvthis)
++{
++ PrivateData *p = drvthis->private_data;
++ unsigned char *fb = p->framebuf;
++ unsigned char *lf = p->lstframe;
++ static unsigned char text[48];
+ int i, line, offset;
+
+- debug(RPT_DEBUG, "picolcd: flush started\n");
++ debug(RPT_DEBUG, "%s: flush started", drvthis->name);
+
+- for (line = 0; line < pd->height; line++) {
+- memset(text, 0, 48);
+- offset = line * pd->width;
+- fb = pd->framebuf + offset;
+- lf = pd->lstframe + offset;
++ for (line = 0; line < p->height; line++) {
++ memset(text, 0, sizeof(text));
++ offset = line * p->width;
++ fb = p->framebuf + offset;
++ lf = p->lstframe + offset;
+
+- for (i = 0; i < pd->width; i++) {
++ for (i = 0; i < p->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);
++ strncpy((char *)text, (char *)p->framebuf +
offset, p->width);
++ p->device->write(p->lcd, line, 0, text);
++ memcpy(p->lstframe + offset, p->framebuf +
offset, p->width);
+
+- debug(RPT_DEBUG, "picolcd: flush wrote line %d
(%s)\n", line + 1,
text);
++ debug(RPT_DEBUG, "%s: flush wrote line %d (%s)",
++ drvthis->name, line + 1, text);
+
+ break;
+ }
+ }
+ }
+
+- debug(RPT_DEBUG, "picolcd: flush complete\n\t(%s)\n\t(%s)\n",
pd->framebuf, pd->lstframe);
++ debug(RPT_DEBUG, "%s: flush complete\n\t(%s)\n\t(%s)",
++ drvthis->name, p->framebuf, p->lstframe);
+ }
+
+-MODULE_EXPORT void picoLCD_string(Driver *drvthis, int x, int y, char
*str) {
+- PrivateData *pd = drvthis->private_data;
+- char *dest;
++
++MODULE_EXPORT void picoLCD_string(Driver *drvthis, int x, int y, unsigned
char *str)
++{
++ PrivateData *p = drvthis->private_data;
++ unsigned char *dest;
+ int len;
+
+- debug(RPT_DEBUG, "picolcd: string start (%s)\n", str);
++ debug(RPT_DEBUG, "%s: string start (%s)", drvthis->name, str);
+
+- if (y < 1 || y > pd->height)
++ if (y < 1 || y > p->height)
+ return;
+- if (x < 1 || x > pd->width)
++ if (x < 1 || x > p->width)
+ return;
+
+- len = strlen(str);
+- if (len + x > pd->width) {
+- debug(RPT_DEBUG, "picolcd: string overlength (>%d). Start: %d
Length: %d (%s)\n", pd->width, x, len ,str);
++ len = strlen((char *)str);
++ if (len + x > p->width) {
++ debug(RPT_DEBUG, "%s: string overlength (>%d). Start: %d
Length: %d
(%s)",
++ drvthis->name, p->width, x, len ,str);
+
+- len = pd->width - x; /* Copy what we can */
++ len = p->width - x; /* Copy what we can */
+ }
+
+ x--; y--; /* Convert 1-based to 0-based */
+- dest = pd->framebuf + (y * pd->width + x);
++ dest = p->framebuf + (y * p->width + x);
+ memcpy(dest, str, len * sizeof(char));
+
+- debug(RPT_DEBUG, "picolcd: string complete (%s)\n", str);
++ debug(RPT_DEBUG, "%s: string complete (%s)", drvthis->name, str);
+ }
+
+-MODULE_EXPORT void picoLCD_chr(Driver *drvthis, int x, int y, char chr) {
+- PrivateData *pd = drvthis->private_data;
+- char *dest;
+
+- debug(RPT_DEBUG, "picolcd: chr start (%c)\n", chr);
++MODULE_EXPORT void picoLCD_chr(Driver *drvthis, int x, int y, unsigned
char chr)
++{
++ PrivateData *p = drvthis->private_data;
++ unsigned char *dest;
++ debug(RPT_DEBUG, "%s: chr start (%c)", drvthis->name, chr);
+
+- if (y < 1 || y > pd->height)
++ if (y < 1 || y > p->height)
+ return;
+- if (x < 1 || x > pd->width)
++ if (x < 1 || x > p->width)
+ return;
+
+ x--; y--; /* Convert 1-based to 0-based */
+- dest = pd->framebuf + (y * pd->width + x);
++ dest = p->framebuf + (y * p->width + x);
+ memcpy(dest, &chr, sizeof(char));
++ debug(RPT_DEBUG, "%s: chr complete (%c)", drvthis->name, chr);
++}
++
+
+- debug(RPT_DEBUG, "picolcd: chr complete (%c)\n", chr);
++
++MODULE_EXPORT void picoLCD_set_char (Driver *drvthis, int n, unsigned
char *dat)
++{
++ PrivateData *p = drvthis->private_data;
++
++ return (p->device->cchar(drvthis, n, dat));
+ }
+
+-/* lcd_logical_driver Essential input functions */
+
++
++MODULE_EXPORT int picoLCD_get_free_chars (Driver *drvthis)
++{
++ return NUM_CCs;
++}
++
++
++MODULE_EXPORT void picoLCD_vbar (Driver *drvthis, int x, int y, int len,
int promille, int options)
++{
++ PrivateData *p = drvthis->private_data;
++
++ if (p->ccmode != vbar) {
++ unsigned char vBar[p->cellheight];
++ int i;
++
++ if (p->ccmode != standard) {
++ /* Not supported(yet) */
++ report(RPT_WARNING, "%s: vbar: cannot combine two modes
using
user-defined characters",
++ drvthis->name);
++ return;
++ }
++ p->ccmode = vbar;
++
++ memset(vBar, 0x00, sizeof(vBar));
++
++ for (i = 1; i < p->cellheight; i++) {
++ // add pixel line per pixel line ...
++ vBar[p->cellheight - i] = 0xFF;
++ picoLCD_set_char(drvthis, i, vBar);
++ }
++ }
++
++ lib_vbar_static(drvthis, x, y, len, promille, options, p->cellheight,
0);
++}
++
++
++MODULE_EXPORT void picoLCD_hbar (Driver *drvthis, int x, int y, int len,
int promille, int options)
++{
++ PrivateData *p = drvthis->private_data;
++
++ if (p->ccmode != hbar) {
++ unsigned char hBar[p->cellheight];
++ int i;
++
++ if (p->ccmode != standard) {
++ /* Not supported(yet) */
++ report(RPT_WARNING, "%s: hbar: cannot combine two modes
using
user-defined characters",
++ drvthis->name);
++ return;
++ }
++
++ p->ccmode = hbar;
++
++ memset(hBar, 0x00, sizeof(hBar));
++
++ for (i = 1; i <= p->cellwidth; i++) {
++ // fill pixel columns from left to right.
++ memset(hBar, 0xFF & ~((1 << (p->cellwidth - i)) - 1),
sizeof(hBar)-1);
++ picoLCD_set_char(drvthis, i, hBar);
++ }
++ }
++
++ lib_hbar_static(drvthis, x, y, len, promille, options, p->cellwidth, 0);
++}
++
++
++MODULE_EXPORT void picoLCD_num (Driver *drvthis, int x, int num)
++{
++ PrivateData *p = drvthis->private_data;
++ int do_init = 0;
++
++ if ((num < 0) || (num > 10))
++ return;
++
++ if (p->ccmode != bignum) {
++ if (p->ccmode != standard) {
++ /* Not supported (yet) */
++ report(RPT_WARNING, "%s: num: cannot combine two modes
using
user-defined characters",
++ drvthis->name);
++ return;
++ }
++
++ p->ccmode = bignum;
++
++ do_init = 1;
++ }
++
++ // Lib_adv_bignum does everything needed to show the bignumbers.
++ lib_adv_bignum(drvthis, x, num, 0, do_init);
++}
++
++
++MODULE_EXPORT int picoLCD_icon (Driver *drvthis, int x, int y, int icon)
++{
++ PrivateData *p = drvthis->private_data;
++
++ /* 8x5 icons each number represents one row in binary */
++
++ static unsigned char heart_open[] =
++ { 0x0, 0xa, 0x15, 0x11, 0x1b, 0xa, 0x4, 0x0 };
++
++
++ static unsigned char heart_filled[] =
++ { 0x0, 0xa, 0x1f, 0x1f, 0x1f, 0xe, 0x4, 0x0 };
++
++ switch (icon) {
++ case ICON_BLOCK_FILLED:
++ picoLCD_chr(drvthis, x, y, 255);
++ break;
++ case ICON_HEART_FILLED:
++ p->ccmode = custom;
++ picoLCD_set_char(drvthis, 7, heart_filled);
++ picoLCD_chr(drvthis, x, y, 7);
++ break;
++ case ICON_HEART_OPEN:
++ p->ccmode = custom;
++ picoLCD_set_char(drvthis, 7, heart_open);
++ picoLCD_chr(drvthis, x, y, 7);
++ break;
++ case ICON_ARROW_LEFT:
++ picoLCD_chr(drvthis, x, y, 127);
++ break;
++ case ICON_ARROW_RIGHT:
++ picoLCD_chr(drvthis, x, y, 126);
++ break;
++
++ default:
++ return -1; /* Let the core do other icons */
++ }
++ return 0;
++}
++
++
++/* lcd_logical_driver Essential input functions */
+ MODULE_EXPORT char *picoLCD_get_key(Driver *drvthis) {
+- PrivateData *pd = drvthis->private_data;
++ PrivateData *p = drvthis->private_data;
+ lcd_packet *keydata;
+- char *keystr;
++ char *keystr = NULL;
+ int keys_read = 0;
+ int key_pass = 0;
+ int two_keys = 0;
+
+- debug(RPT_DEBUG, "picolcd: get_key start (timeout %d)\n",
pd->key_timeout);
++ debug(RPT_DEBUG, "%s: get_key start (timeout %d)",
++ drvthis->name, p->key_timeout);
+
+ keydata = malloc(sizeof(lcd_packet));
+
+ while (! keys_read) {
+- get_key_event(pd->lcd, keydata, pd->key_timeout);
+- debug(RPT_DEBUG, "picolcd: get_key got an event\n");
++ get_key_event(p->lcd, keydata, p->key_timeout);
++ debug(RPT_DEBUG, "%s: get_key got an event", drvthis->name);
+
+ if (keydata->type == IN_REPORT_KEY_STATE) {
+ if (! keydata->data[1] && key_pass) {
+- debug(RPT_DEBUG, "picolcd: get_key got all
clear\n");
++ debug(RPT_DEBUG, "%s: get_key got all clear",
drvthis->name);
+ /* 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) {
+- debug(RPT_DEBUG, "picolcd: get_key got one
key\n");
++ debug(RPT_DEBUG, "%s: get_key got one key",
drvthis->name);
+ /* We got one key (but not after a two key
event and before and all
clear) */
+- keystr = pd->key_matrix[keydata->data[1]];
++ keystr = p->device->keymap[keydata->data[1]];
+ } else {
+ /* We got two keys */
+- debug(RPT_DEBUG, "picolcd: get_key got two
keys\n");
++ debug(RPT_DEBUG, "%s: get_key got two keys",
drvthis->name);
+ two_keys++;
+- sprintf(keystr, "%s+%s",
pd->key_matrix[keydata->data[1]],
pd->key_matrix[keydata->data[2]]);
++ sprintf(keystr, "%s+%s",
p->device->keymap[keydata->data[1]],
p->device->keymap[keydata->data[2]]);
+ }
+
+ key_pass++; /* This hack allows us to deal with
receiving left over
<0,0> first */
++ } else if (p->IRenabled && keydata->type == IN_REPORT_IR_DATA) {
++ int cbres;
++
++ debug(RPT_NOTICE, "%s: get_key irdata, length=%d bytes",
++ drvthis->name, keydata->data[1]);
++
++ cbres = ir_transcode(drvthis, (keydata->data)+2,
keydata->data[1],
p->result, sizeof(p->result));
++ debug(RPT_NOTICE, "%s: get_key irdata transcoded,
count=%d bytes",
++ drvthis->name, cbres);
++
++ if (cbres < 0) {
++ report(RPT_ERR, "%s: could not transcode
buffer, length=%d",
++ drvthis->name, keydata->data[1]);
++ } else {
++ debug(RPT_NOTICE, "%s: sending packet to lirc,
length=%d",
++ drvthis->name, cbres);
++ int ret = sendto(p->lircsock, p->result, cbres, 0,
++ (struct sockaddr *) &(p->lircserver),
sizeof(p->lircserver));
++ if (ret == -1) {
++ report(RPT_ERR, "%s: error sending UDP packet,
errno=%d",
++ drvthis->name, errno);
++ } else if (ret != cbres) {
++ report(RPT_ERR, "%s: mismatch in number of
bytes sent (%d!=%d)",
++ drvthis->name, cbres, ret);
++ } else {
++ debug(RPT_NOTICE, "%s: packet sent to lirc.",
drvthis->name);
++ }
++ }
+ } else {
+- debug(RPT_DEBUG, "picolcd: get_key got non-key data or
timeout\n");
++ debug(RPT_DEBUG, "%s: get_key got non-key data or
timeout",
drvthis->name);
+ /* We got IR or otherwise bad data */
++ free(keydata);
+ return NULL;
+ }
+
+ }
+
+- free(keydata);
++ free(keydata);
+
+- debug(RPT_DEBUG, "picolcd: get_key complete (%s)\n", keystr);
++ debug(RPT_DEBUG, "%s: get_key complete (%s)", drvthis->name, keystr);
+
+- if (! strlen(keystr))
+- return NULL;
++ if ((keystr != NULL) && (strlen(keystr) > 0))
++ return keystr;
+
+- return keystr;
++ return NULL;
+
+ /*
+ * Due to how key events are reported, we need to keep reading key presses
+@@ -352,21 +668,6 @@
+ * 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: <high key, low key>.
+- *
+- * 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.
+ *
+@@ -381,62 +682,97 @@
+ *
+ * What this means is that we need to keep reading key presses until we
get
+ * the <0, 0> all clear.
++ *
++ * For keymapping see the picolcd_device structs.
+ */
+
+ }
+
++
+ /* 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_get_contrast(Driver *drvthis)
++{
++ PrivateData *p = 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 */
+
++MODULE_EXPORT int picoLCD_set_contrast(Driver *drvthis, int promille)
++{
++ PrivateData *p = drvthis->private_data;
++ int inv; /* The hardware seems to go dark on higher values, so we turn
it around */
++ unsigned char packet[2] = { 0x92 }; /* set contrast id */
++
++
++
+ if (promille <= 1000 && promille > 0) {
+- inv = 1000 - promille;
+- pd->lcd->contrast(pd->lcd, (int) (inv / 1000 * 40));
+- return 0;
++ if (p->device->contrast_max == 1)
++ packet[1] = 0x00; /* picoLCD20x4 permits contrast as
0/1 value */
++ else {
++ inv = 1000 - promille;
++ packet[1] = inv / 1000 * p->device->contrast_max;
++ }
+ } else if (promille > 1000) {
+- pd->lcd->contrast(pd->lcd, 0);
+- return 0;
++ packet[1] = p->device->contrast_min;
+ } else if (promille <= 0) {
+- pd->lcd->contrast(pd->lcd, 40);
+- return 0;
++ packet[1] = p->device->contrast_max;
+ } else {
+ return -1;
+ }
++
++ picolcd_send(p->lcd, packet, 2);
++
++ return 0;
+ }
+
+-/*MODULE_EXPORT int picoLCD_get_brightness(Driver *drvthis, int state) {
+- PrivateData *pd = drvthis->private_data;
++/*MODULE_EXPORT int picoLCD_get_brightness(Driver *drvthis, int state)
++{
++ PrivateData *p = drvthis->private_data;
+
+ }*/
+
+-/*MODULE_EXPORT int picoLCD_set_brightness(Driver *drvthis, int state,
int promille) {
+- PrivateData *pd = drvthis->private_data;
+-
+-}*/
++MODULE_EXPORT void picoLCD_set_brightness(Driver *drvthis, int state, int
promille)
++{
++ PrivateData *p = drvthis->private_data;
++
++ if (promille < 0 || promille > 1000)
++ return;
++
++ if (state)
++ p->brightness = promille;
++
++ return;
++}
+
+-MODULE_EXPORT void picoLCD_backlight(Driver *drvthis, int state) {
+- PrivateData *pd = drvthis->private_data;
+
++MODULE_EXPORT void picoLCD_backlight(Driver *drvthis, int state)
++{
++ PrivateData *p = drvthis->private_data;
++ unsigned char packet[2] = { 0x91 }; /* set backlight id */
++
++ int s = p->brightness / 10; /* scale in 0-100 range for picoLCDs */
++
++ /* picoLCD 20x2 doesn't have brightness levels */
++ if (s > p->device->bklight_max)
++ s = p->device->bklight_max;
++
+ if (state == 0) {
+- pd->lcd->backlight(pd->lcd, state);
+- set_key_lights(pd->lcd, pd->key_light, state);
++ //packet[1] = (unsigned char) p->device->bklight_min;
++ packet[1] = 0xff;
++ picolcd_send(p->lcd, packet, 2);
++ set_key_lights(p->lcd, p->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);
++ packet[1] = (unsigned char) s;
++ picolcd_send(p->lcd, packet, 2);
++ if (p->keylights)
++ set_key_lights(p->lcd, p->key_light, state);
+ return;
+ }
+
+@@ -444,24 +780,258 @@
+ }
+
+ /*MODULE_EXPORT int picoLCD_output(Driver *drvthis, int state) {
+- PrivateData *pd = drvthis->private_data;
++ PrivateData *p = drvthis->private_data;
+
+ }*/
+
++
+ /* lcd_logical_driver Informational functions */
+ MODULE_EXPORT char *picoLCD_get_info(Driver *drvthis) {
+- PrivateData *pd = drvthis->private_data;
++ PrivateData *p = drvthis->private_data;
+
+- return pd->info;
++ return p->info;
+ }
+
++
+ /* Private functions */
+-void get_key_event (usblcd_operations *self, lcd_packet *packet, int
timeout) {
++
++/*
++ * Transcode from picoLCD USB format to LIRC UDP format.
++ * LIRC UDP packets expect 16-bit intervals, with MSB set for space.
++ * Intervals are measured in jiffies (1/16384 s).
++ * PicoLCD USB packets contain 16-bit intervals, with value negated
++ * for space. Intervals are in microseconds.
++ * PicoLCD presents the bytes in network order, and they must be put back
++ * in that order for transmission via UDP.
++ * One jiffy == 61 us. 537 us == 9j.
++ *
++ * drvthis: driver data (used for debug() and report()).
++ * data, cbdata: buffer of integers to be transcoded.
++ * result,
++ * cbresult: buffer to receive the transcoded values.
++ * @return: number of bytes placed in result buffer.
++ */
++static int ir_transcode(Driver *drvthis, unsigned char *data, unsigned
int cbdata,
++ unsigned char *result, int
cbresult)
++{
++ PrivateData *p = drvthis->private_data;
++ int i;
++ int cIntervals = cbdata >> 1;
++ int resptr = 0;
++ long w = (data[1] << 8) + data[0];
++
++ //Check for odd buffer length (invalid buffer)
++ if (cbdata & 1) {
++ return -1;
++ }
++
++ /*
++ * Look for an initial long PULSE, and frig it for LIRC's benefit:
++ * add a sync SPACE in front.
++ */
++ if (w & 0x8000) { /* SPACE */
++ w = 65536 - w;
++ if (w > 8000) {
++ /*
++ * The signal was a space longer than 8000 ms, i.e.
probably a sync. We
++ * now expect from picoLCD either a repeat-code, or a
long pulse
followed
++ * by a full code.
++ * Lirc expects a sync (SPACE) followed by either a
header
(pulse/space)
++ * or a repeat-code.
++ * Lirc is also expecting active-low signalling. So we
emit the
required
++ * sync, then the signals from picoLCD with arity
inverted.
++ * Emit sync space to LIRC (0x8040, = 64 jiffies, =
3900usec).
++ */
++ if (p->sync) {
++ result[resptr++] = p->sync;
++ result[resptr++] = 0x80;
++ }
++ p->gap = p->preset_gap;
++ debug(RPT_DEBUG, "%s: preset gap, length=%d jiffies",
++ drvthis->name, p->gap);
++ }
++ }
++ for (i = 0; i < cIntervals; i++) {
++ long w = (data[i*2 + 1] << 8) + data[i*2];
++
++ if (w & 0x8000) {
++ //IF w is negative THEN negate. E.g. 0xDCA1 (-9055) ->
9055.
++ w = 0x10000 - w;
++ //scale: orig is usec, new is jiffy. E.g. 9055usec =
148 jiffy.
++ w = (w * 16384 /1000000) & 0xFFFF;
++ p->gap -= w;
++ } else {
++ //Scale.
++ w = w * 16384 / 1000000;
++ //Set the space bit.
++ p->gap -= w;
++ w |= 0x8000;
++ }
++ if (resptr + 2 < cbresult) {
++ result[resptr++] = w & 0xFF;
++ result[resptr++] = (w >> 8) & 0xFF;
++ } else {
++ resptr = -1;
++ break;
++ }
++ }
++ /*
++ * Look for a short buffer with a terminal PULSE, and frig it for
LIRC's
benefit:
++ * add a gap SPACE after. This is an ugly gash; it won't work if the
code ends with
++ * a buffer containing exactly ten intervals.
++ */
++ if (resptr > 0 && cIntervals < 10) {
++ if (resptr + 2 < cbresult) {
++ int last = cIntervals -1;
++
++ w = (data[last*2 + 1] << 8) + data[last*2];
++ if (p->gap > 0) {
++ if (w & 0x8000) {
++ //terminal pulse
++ debug(RPT_DEBUG, "%s: appending gap,
length=%d jiffies",
++ drvthis->name, p->gap);
++ p->gap |= 0x8000;
++ result[resptr++] = p->gap & 0xFF;
++ result[resptr++] = (p->gap >>8) & 0xFF;
++ } else {
++ debug(RPT_DEBUG, "%s: terminal
space=[%04x]; not appending gap
(length=%d jiffies)", (unsigned int)(w & 0xffff), drvthis->name, p->gap);
++ }
++ } else {
++ debug(RPT_DEBUG, "%s: not appending gap because
it would be negative
(length=%d jiffies)", drvthis->name, p->gap);
++ }
++ } else {
++ //Result buffer would overflow
++ resptr = -1;
++ }
++ } else {
++ debug(RPT_DEBUG, "%s: cIntervals=%d; not appending gap
(length=%d
jiffies)",
++ drvthis->name, cIntervals, p->gap);
++ }
++ return resptr;
++}
++
++
++static void picolcd_send(usb_dev_handle *lcd, unsigned char *data, int
size)
++{
++ if ((lcd == NULL) && (data == NULL))
++ return;
++
++ usb_interrupt_write(lcd, USB_ENDPOINT_OUT + 1, (char *) data,
size, 1000);
++}
++
++static void picolcd_20x4_write(usb_dev_handle *lcd, const int row, const
int col, const unsigned char *data)
++{
++ unsigned char packet[64];
++
++ unsigned char lineset[4][6] = {
++ { 0x94, 0x00, 0x01, 0x00, 0x64, 0x80 },
++ { 0x94, 0x00, 0x01, 0x00, 0x64, 0xC0 },
++ { 0x94, 0x00, 0x01, 0x00, 0x64, 0x94 },
++ { 0x94, 0x00, 0x01, 0x00, 0x64, 0xD4 }
++ };
++
++ int len, i;
++
++ switch(row) {
++ case 0: picolcd_send(lcd, lineset[0], 6); break;
++ case 1: picolcd_send(lcd, lineset[1], 6); break;
++ case 2: picolcd_send(lcd, lineset[2], 6); break;
++ case 3: picolcd_send(lcd, lineset[3], 6); break;
++ default: picolcd_send(lcd, lineset[0], 6); break;
++ }
++
++ len = strlen((char *)data);
++ if (len > 20) len = 20;
++
++ packet[0] = 0x95;
++ packet[1] = 0x01;
++ packet[2] = 0x00;
++ packet[3] = 0x01;
++ packet[4] = len;
++
++ i = 5;
++ while (len--) {
++ packet[i++] = *data++;
++ }
++
++ picolcd_send(lcd, packet, i);
++}
++
++
++static void picolcd_20x2_write(usb_dev_handle *lcd, const int row, const
int col, const unsigned char *data)
++{
++ unsigned char packet[64];
++ int len, i;
++
++ len = strlen((char *)data);
++ if (len > 20) len = 20;
++
++ packet[0] = 0x98;
++ packet[1] = row;
++ packet[2] = col;
++ packet[3] = len;
++
++ i = 4;
++ while (len--) {
++ packet[i++] = *data++;
++ }
++
++ picolcd_send(lcd, packet, i);
++}
++
++static void picolcd_20x2_set_char (Driver *drvthis, int n, unsigned char
*dat)
++{
++ PrivateData *p = drvthis->private_data;
++ unsigned char packet[10] = { 0x9c }; /* define character */
++ unsigned char mask = (1 << p->cellwidth) - 1;
++ int row;
++
++ if ((n < 0) || (n >= NUM_CCs))
++ return;
++ if (!dat)
++ return;
++
++ packet[1] = n; /* Custom char to define. */
++
++ for (row = 0; row < p->cellheight; row++) {
++ packet[row + 2] = dat[row] & mask;
++ }
++
++ picolcd_send(p->lcd, packet, 10);
++
++ return;
++}
++
++
++static void picolcd_20x4_set_char (Driver *drvthis, int n, unsigned char
*dat)
++{
++
++ if ((n < 0) || (n >= NUM_CCs))
++ return;
++ if (!dat)
++ return;
++
++ PrivateData *p = drvthis->private_data;
++ unsigned char command[6] = { OUT_REPORT_CMD, 0x00, 0x01, 0x00, 0x64,
0x40+8*n }; /* 0x94 */
++ unsigned char data[13] = { OUT_REPORT_DATA, 0x01, 0x00, 0x01, 0x08,
++ dat[0], dat[1], dat[2], dat[3],
++ dat[4], dat[5], dat[6], dat[7]};
/* 0x95 */
++
++ picolcd_send(p->lcd, command, 6);
++ picolcd_send(p->lcd, data, 13);
++
++ return;
++}
++
++
++static void get_key_event(usb_dev_handle *lcd, 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);
++
++ ret = usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char
*)packet->data,
PICOLCD_MAX_DATA_LEN, timeout);
+ if (ret > 0) {
+ switch (packet->data[0]) {
+ case IN_REPORT_KEY_STATE: {
+@@ -469,6 +1039,13 @@
+ } break;
+ case IN_REPORT_IR_DATA: {
+ packet->type = IN_REPORT_IR_DATA;
++ /*
++ * clears the halt status on the usb
endpoint
++ * picoLCD 20x4 keeps last ir state
without clearing the
++ * status on endpoint, meaning that we
will get same IR data
++ * over and over till we clear the status
manually.
++ */
++ usb_clear_halt(lcd, USB_ENDPOINT_IN + 1);
+ } break;
+ default: {
+ packet->type = 0;
+@@ -477,28 +1054,26 @@
+ }
+ }
+
+-void set_key_lights (usblcd_operations *self, int keys[], int state) {
++
++static void set_key_lights(usb_dev_handle *lcd, int keys[], int state)
++{
++ unsigned char packet[2] = { 0x81 }; /* set led */
++ unsigned int leds = 0;
++ int i;
++
+ 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);
++ for (i = 0; i < KEYPAD_LIGHTS; i++)
++ if(keys[i])
++ leds |= 1 << i;
++ else
++ leds &= ~ (1 << i);
+ } 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);
++ leds = 0;
+ }
++
++ packet[1] = leds;
++ picolcd_send(lcd, packet, 2);
+ }
++
+diff -Naur lcdproc-0.5.2-old/server/drivers/picolcd.h
lcdproc-0.5.2-new/server/drivers/picolcd.h
+--- lcdproc-0.5.2-old/server/drivers/picolcd.h 2007-04-14
07:38:14.000000000 -0700
++++ lcdproc-0.5.2-new/server/drivers/picolcd.h 2009-01-21
15:28:04.000000000 -0800
+@@ -1,56 +1,112 @@
+ /*
+- * Driver for picoLCD graphical displays
+- * Header file
++ * picoLCD driver for lcdPROC
+ *
+ * (c) 2007 NitroSecurity, Inc.
+ * Written by Gatewood Green <[email protected]> or
<[email protected]>
+- *
++ * (c) 2007-2008 Peter Marschall - adapted coding style and reporting to
LCDproc
++ * (c) 2007 Mini-Box.com, Nicu Pavel <[email protected]>
++ * - removed libusblcd and hid dependency
++ * - added vbar, hbar, custom char, bignum support
++ * (c) 2008 Jack Cleaver - add LIRC connection
++ * (c) 2008 Mini-Box.com Nicu Pavel <[email protected]>
++ * - Added support for 4x20 picoLCD
+ * 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
++ * picoLCD 4x20: http://www.mini-box.com/PicoLCD-4X20-Sideshow
+ *
+- * See picolcd.c for full details
++ * The picoLCD is usb connected and is driven (currently) via userspace
++ * using libusb library.
+ *
++ * libusb: http://libusb.sf.net
++ *
+ */
+
+ #ifndef PICOLCD_H
+ #define PCIOLCD_H
+
+ #include "lcd.h"
++#include "lcd_lib.h"
++#include "adv_bignum.h"
++
++#include <usb.h>
++
++/* 12 keys plus a 0 placeholder */
++#define KEYPAD_MAX 13
++#define KEYPAD_LIGHTS 8
++
++#define picoLCD_VENDOR 0x04d8
++#define picoLCD_DEVICE 0x0002
++
++#define IN_REPORT_KEY_STATE 0x11
++#define IN_REPORT_IR_DATA 0x21
++
++#define OUT_REPORT_CMD 0x94
++#define OUT_REPORT_DATA 0x95
++
++#define PICOLCD_MAX_DATA_LEN 24
++
++#define DEFAULT_LIRCPORT 8765
++#define DEFAULT_SYNC_JIFFY 64
++#define DEFAULT_LENGTH_JIFFY 2048
++
+
+ typedef struct _lcd_packet lcd_packet;
++
+ struct _lcd_packet {
+ unsigned char data[255];
+ unsigned int type;
+ };
+
++typedef struct _picolcd_device picolcd_device ;
++
++struct _picolcd_device {
++ char *device_name; /* Device name */
++ char *description; /* Device description */
++ unsigned char initseq[PICOLCD_MAX_DATA_LEN]; /* init sequence
*/
++ char *keymap[KEYPAD_MAX]; /* key pad button names */
++ unsigned int vendor_id; /* vendor id for detection */
++ unsigned int device_id; /* device id for detection */
++ int bklight_max; /* maximum backlight value */
++ int bklight_min; /* minimum backlight value */
++ int contrast_max; /* contrast maximum value */
++ int contrast_min; /* minimum contrast value */
++ int width; /* width of lcd screen */
++ int height; /* height of lcd screen */
++ /* Pointer to function that writes data to the LCD format */
++ void (*write)(usb_dev_handle *lcd, const int row, const int col,
const unsigned char *data);
++ /* Pointer to function that defines a custom character */
++ void (*cchar) (Driver *drvthis, int n, unsigned char *dat);
++};
++
+ 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 void picoLCD_string(Driver *drvthis, int x, int y, unsigned
char *str);
++MODULE_EXPORT void picoLCD_chr(Driver *drvthis, int x, int y, unsigned
char c);
++MODULE_EXPORT void picoLCD_set_char (Driver *drvthis, int n, unsigned
char *dat);
+ 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 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 num);
++MODULE_EXPORT int 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_set_brightness (Driver *drvthis, int state,
int promille);
+ MODULE_EXPORT void picoLCD_backlight(Driver *drvthis, int promille);
++MODULE_EXPORT char *picoLCD_get_info(Driver *drvthis);
++
+ //MODULE_EXPORT void picoLCD_output(Driver *drvthis, int state);
++//MODULE_EXPORT int picoLCD_get_contrast(Driver *drvthis);
++//MODULE_EXPORT int picoLCD_get_brightness (Driver *drvthis, int state);
++
+
+-MODULE_EXPORT char *picoLCD_get_info(Driver *drvthis);
+
+ #endif
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"minimyth-commits" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/minimyth-commits?hl=en
-~----------~----~----~----~------~----~------~--~---