diff -urN lcdproc-cvs/server/drivers/picolcd.c lcdproc-picolcd/server/drivers/picolcd.c
--- lcdproc-cvs/server/drivers/picolcd.c	2008-10-02 02:39:45.000000000 +0300
+++ lcdproc-picolcd/server/drivers/picolcd.c	2008-10-02 02:41:04.000000000 +0300
@@ -8,15 +8,14 @@
  *     - 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 <npavel@mini-box.com>
+ *      - 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 
  * using libusb library.
@@ -49,14 +48,11 @@
 #include <netinet/in.h>
 #include <arpa/inet.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 */
+#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 */ 
 
@@ -69,7 +65,6 @@
 	bigchar		/* big characters */
 } CGmode;
 
-
 /* PrivateData struct */
 typedef struct pd {
 	usb_dev_handle *lcd;
@@ -80,15 +75,16 @@
 	int  key_timeout;
 	int  contrast;
 	int  backlight;
+	int  brightness;
 	int  keylights;
 	int  key_light[KEYPAD_LIGHTS];
 	/* defineable characters */
 	CGmode ccmode;
-	char *key_matrix[KEYPAD_MAX];
 	char *info;
 	unsigned char *framebuf;
 	unsigned char *lstframe;
-
+        /* device info struct */
+        picolcd_device *device;
 	int IRenabled;
 	//For communicating with LIRC
 	int lircsock;
@@ -100,30 +96,61 @@
 	int gap;
 } PrivateData;
 
-static char * keymap[KEYPAD_MAX] = {
-	NULL,
-	"Plus",
-	"Minus",
-	"F1",
-	"F2",
-	"F3",
-	"F4",
-	"F5",
-	"Left",
-	"Right",
-	"Up",
-	"Down",
-	"Enter"
-};
-
 /* Private function definitions */
 static void picolcd_send(usb_dev_handle *lcd, unsigned char *data, int size);
-static void picolcd_write(usb_dev_handle *lcd, const int row, const int col, const unsigned char *data);
+/* 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;
 MODULE_EXPORT int  stay_in_foreground = 0;
@@ -138,6 +165,7 @@
 	struct usb_device *dev;
 	const char *lirchost;
 	int lircport;
+        int id;
 
 	p = (PrivateData *) malloc(sizeof(PrivateData));
 	if (p == NULL)
@@ -152,59 +180,58 @@
 	usb_find_devices();
 
 	p->lcd = NULL;
-	for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
-		for (dev = bus->devices; dev != NULL; dev = dev->next) {
-			if ((dev->descriptor.idVendor == picoLCD_VENDOR) &&
-				(dev->descriptor.idProduct == picoLCD_DEVICE)) {
+        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 picoLCD on bus %s device %s", bus->dirname, dev->filename);
-				p->lcd = usb_open(dev);
-				goto done;
-			}
-		}
-	}
+		                      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);
-
-		if (usb_set_configuration(p->lcd, 0) < 0) {
-			usb_close(p->lcd);
-			report(RPT_ERR, "%s: unable to set configuration", drvthis->name);
-			return -1;
-		}
-		usleep(100);
-
-		if (usb_claim_interface(p->lcd, 0) < 0) {
-#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
-			if ((usb_detach_kernel_driver_np(p->lcd, 0) < 0) ||
-				(usb_claim_interface(p->lcd, 0) < 0)) {
 #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'", driver);
+                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
-				usb_close(p->lcd);
-				report(RPT_ERR, "%s: unable to re-claim interface", drvthis->name);
-			        return -1;
-			}
-#else
-			report(RPT_ERR, "%s: failed to claim interface", drvthis->name);
+                }
+#endif
+		if (usb_claim_interface(p->lcd, 0) < 0) {
+			report(RPT_ERR, "Cannot claim interface !", driver);
 			usb_close(p->lcd);
 			return -1;
-#endif
 		}
-
+		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;
-	}		
+        } else {
+                report(RPT_ERR, "%s: no device found", drvthis->name);
+                return -1;
+        }		
 	
-	p->width  = 20; /* hard coded (mfg spec) */
-	p->height = 2;  /* hard coded (mfg spec) */
-	p->info = "picoLCD: Supports the LCD as installed on the M300 (http://www.mini-box.com/Mini-Box-M300-LCD) ";
+        /* 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;
@@ -213,20 +240,20 @@
 		p->key_light[x] = 1; /* individual lights on */
 
 	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 */
-	p->key_light[0] = drvthis->config_get_bool(drvthis->name, "Key0Light",  0, 1); /* Directional PAD */
-	p->key_light[1] = drvthis->config_get_bool(drvthis->name, "Key1Light",  0, 1); /* F1 */
-	p->key_light[2] = drvthis->config_get_bool(drvthis->name, "Key2Light",  0, 1); /* F2 */
-	p->key_light[3] = drvthis->config_get_bool(drvthis->name, "Key3Light",  0, 1); /* F3 */
-	p->key_light[4] = drvthis->config_get_bool(drvthis->name, "Key4Light",  0, 1); /* F4 */
-	p->key_light[5] = drvthis->config_get_bool(drvthis->name, "Key5Light",  0, 1); /* F5 */
-
-	for (x = 0; x < KEYPAD_MAX; x++)
-		p->key_matrix[x] = keymap[x];
+	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) {
@@ -347,7 +374,7 @@
 		for (i = 0; i < p->width; i++) {
 			if (*fb++ != *lf++) {
 				strncpy((char *)text, (char *)p->framebuf + offset, p->width);
-				picolcd_write(p->lcd, line, 0, text);
+				p->device->write(p->lcd, line, 0, text);
 				memcpy(p->lstframe + offset, p->framebuf + offset, p->width);
 
 				debug(RPT_DEBUG, "%s: flush wrote line %d (%s)",
@@ -410,28 +437,16 @@
 }
 
 
+
 MODULE_EXPORT void picoLCD_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 (p->device->cchar(drvthis, n, dat));
 }
 
 
+
 MODULE_EXPORT int picoLCD_get_free_chars (Driver *drvthis)
 {
 	return NUM_CCs;
@@ -590,12 +605,12 @@
 			} else if (! keydata->data[2] && ! two_keys) {
 				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 = p->key_matrix[keydata->data[1]];
+				keystr = p->device->keymap[keydata->data[1]];
 			} else {
 				/* We got two keys */
 				debug(RPT_DEBUG, "%s: get_key got two keys", drvthis->name);
 				two_keys++;
-				sprintf(keystr, "%s+%s", p->key_matrix[keydata->data[1]], p->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 */
@@ -653,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.
  *
@@ -682,6 +682,8 @@
  *
  * 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.
  */
 	
 }
@@ -705,35 +707,46 @@
 	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;
-		packet[1] =  inv / 1000 * 40;
+		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) {
-		packet[1] = 0;
+		packet[1] = p->device->contrast_min;
 	} else if (promille <= 0) {
-		packet[1] = 40;
+		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 *p = drvthis->private_data;
 
 }*/
 
-
-/*MODULE_EXPORT int  picoLCD_set_brightness(Driver *drvthis, int state, int promille)
+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)
@@ -741,15 +754,22 @@
 	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) {
-		packet[1] = 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) {
-		packet[1] = state;
+		packet[1] = (unsigned char) s;
 		picolcd_send(p->lcd, packet, 2);
 		if (p->keylights)
 			set_key_lights(p->lcd, p->key_light, state);
@@ -893,11 +913,52 @@
 
 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++;
+        }
 
-static void picolcd_write(usb_dev_handle *lcd, const int row, const int col, const unsigned char *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;
@@ -918,6 +979,50 @@
 	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)
 {
@@ -925,6 +1030,7 @@
 
 	memset(packet->data, 0, 255);
 	packet->type = 0;
+        
 	ret = usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char *)packet->data, PICOLCD_MAX_DATA_LEN, timeout);
 	if (ret > 0) {
 		switch (packet->data[0]) {
@@ -933,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;
@@ -950,7 +1063,7 @@
     
 	if (state) {
 		/* Only LEDs we want on */
-		for (i = 0; i < picoLCD_MAX_LEDS; i++) 
+		for (i = 0; i < KEYPAD_LIGHTS; i++) 
 			if(keys[i]) 
 				leds |= 1 << i;
 			else 
diff -urN lcdproc-cvs/server/drivers/picolcd.h lcdproc-picolcd/server/drivers/picolcd.h
--- lcdproc-cvs/server/drivers/picolcd.h	2008-10-02 02:39:46.000000000 +0300
+++ lcdproc-picolcd/server/drivers/picolcd.h	2008-10-02 02:41:04.000000000 +0300
@@ -1,20 +1,27 @@
 /*
- * Driver for picoLCD graphical displays
- * Header file
+ * picoLCD driver for lcdPROC
  *
  * (c) 2007 NitroSecurity, Inc.
  * Written by Gatewood Green <woody@nitrosecurity.com> or <woody@linif.org>
- * (c) 2007 Mini-Box.com.
- * <npavel@ituner.com> removed libusblcd dependency
- *
+ * (c) 2007-2008 Peter Marschall - adapted coding style and reporting to LCDproc
+ * (c) 2007 Mini-Box.com, Nicu Pavel <npavel@ituner.com> 
+ *     - 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 <npavel@mini-box.com>
+ *      - 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
@@ -24,14 +31,21 @@
 #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 picoLCD_MAX_LEDS 6
-
 #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
@@ -46,6 +60,26 @@
 	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);
@@ -64,13 +98,15 @@
 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

