--- bluez-utils-3.8/hidd/fakehid.c	2006-12-29 18:37:41.000000000 -0500
+++ bluez-utils-3.8/hidd/fakehid.c	2007-01-08 23:13:46.000000000 -0500
@@ -522,20 +522,25 @@
 }
 
 /************************ Logitech Mediapad Driver ********************************
- *     (C) 2006 Tim Hentenaar <tim@hentenaar.com>                                 *
+ *     (C) 2006-2007 Tim Hentenaar <tim@hentenaar.com>                            *
  *     Licensed under the GNU General Public License.                             *
  *     The latest version of this work is available at http://hentenaar.com       *
  *                                                                                *
+ *     Updates:                                                                   *
+ *     		Thanks to Glen Rolle for suggesting the single-line write         *
+ *     		mode, and for showing me a better method for writing chars        *
+ *     		>= 0x80 from python.
+ *                                                                                *
  *     Notes:                                                                     *
- *		1) The i18n for the device isn't currently supported.              *
- *			The way that the i18n works, is that when the device       *
- *			connects, the Winblows app retrieves the respective        *
- *			strings from the device and verifies/updates them.         *
+ *		1) The i18n for the device isn't currently supported.             *
+ *			The way that the i18n works, is that when the device      *
+ *			connects, the Winblows app retrieves the respective       *
+ *			strings from the device and verifies/updates them.        *
  *                                                                                *
- *			Simple enough to do, but I'll worry about it later.        *
- *		2) The '000' key actually sends 3 0's and is not a special key.    *
- *		3) The "Copy calulator result to clipboard" requires an            *
- *		   activation packet that I haven't isolated to date.              *
+ *			Simple enough to do, but I'll worry about it later.       *
+ *		2) The '000' key actually sends 3 0's and is not a special key.   *
+ *		3) The "Copy calulator result to clipboard" requires an           *
+ *		   activation packet that I haven't isolated to date.             *
  *              4) Git-R-Done!                                                    *
  **********************************************************************************/
 
@@ -586,7 +591,21 @@
 	{{ 0xA2, 0x10, 0x00, 0x83, 0x11, 0x00, 0x00, 0x00 }, 8},
 	{{ 0 }, 0}
 };
+
+struct mpcmd write_lcd_single[] = { /* Write a single line of text to the LCD */ 
+	{{ 0xA2, 0x10, 0x00, 0x81, 0x10, 0x00, 0x00, 0x00 }, 8},
+	{{ 0xA2, 0x10, 0x00, 0x80, 0x12, 0x10, 0x10, 0x10 }, 8},
+	{{ 0xA2, 0x10, 0x00, 0x81, 0x10, 0x00, 0x00, 0x00 }, 8},
+	{{ 0xA2, 0x11, 0x00, 0x82, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 21},
+	{{ 0xA2, 0x11, 0x00, 0x82, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 21},
+	{{ 0xA2, 0x11, 0x00, 0x82, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 21},
+	{{ 0xA2, 0x10, 0x00, 0x80, 0x12, 0x10, 0x10, 0x10 }, 8},
+	{{ 0xA2, 0x10, 0x00, 0x83, 0x11, 0x00, 0x00, 0x00 }, 8},
+	{{ 0 }, 0}
+};
+
 #define N_LCDW_CMDS	14
+#define N_LCDS_CMDS	8
 
 /* LCD Line Flags */
 #define LCD_LINE_DISPLAY	0x10
@@ -646,6 +665,20 @@
 "              <!-- Max Length: 144 -->\n"
 "              <arg name=\"text\" type=\"s\" direction=\"in\"/>\n"
 "           </method>\n"
+"            <method name=\"WriteLine\">\n"
+"              <!-- Max Length: 48 -->\n"
+"              <arg name=\"lineno\" type=\"u\" direction=\"in\"/>\n"
+"              <arg name=\"text\"   type=\"s\" direction=\"in\"/>\n"
+"           </method>\n"
+"            <method name=\"WriteTextBin\">\n"
+"              <!-- Max Length: 144 -->\n"
+"              <arg name=\"text\" type=\"ai\" direction=\"in\"/>\n"
+"           </method>\n"
+"            <method name=\"WriteLineBin\">\n"
+"              <!-- Max Length: 48 -->\n"
+"              <arg name=\"lineno\" type=\"u\"  direction=\"in\"/>\n"
+"              <arg name=\"text\"   type=\"ai\" direction=\"in\"/>\n"
+"           </method>\n"
 "         </interface>\n"
 "       </node>\n";
 
@@ -713,7 +746,6 @@
 	while (setclk[i].len != 0) { write(sock,setclk[i].command,setclk[i].len); i++; }
 }
 
-
 static void write_lcd_text(int sock, char *text) {
 	char lines[16*9]; struct mpcmd *lcdw = NULL; uint32_t i = 0,z = 0,line = 0; uint8_t f1 = LCD_LINE_DISPLAY, f2 = LCD_LINE_DISPLAY, f3 = LCD_LINE_DISPLAY;
 
@@ -748,10 +780,44 @@
 	lcdw[12].command[6] = f2;
 	lcdw[12].command[7] = f3;		
 	i = 0; while (lcdw[i].len != 0) { write(sock,lcdw[i].command,lcdw[i].len); i++; } free(lcdw);
+}	
+
+static void write_lcd_line(int sock, char *text, int lineno) {
+	char lines[16*3]; struct mpcmd *lcdw = NULL; uint32_t i = 0,z = 0,line = 0; uint8_t f = LCD_LINE_DISPLAY;
+
+	if (!text || sock < 4) return; lineno = (lineno > 3) ? 3 : (lineno <= 0) ? 1 : lineno;
+	memset(lines,0x20,16*3); z = (strlen(text) > 16*3) ? 16*3 : strlen(text);
+	for (i=0;i<z;i+=16) {
+		line = i / 16;
+		memcpy(lines+(16*line),text+i,((z-i) < 16) ?  (z-i) : 16);
+	}
+
+	lcdw = malloc(sizeof(struct mpcmd)*N_LCDS_CMDS); 
+	memcpy(lcdw,write_lcd_single,sizeof(struct mpcmd)*N_LCDS_CMDS);
+	
+	/* Copy the line text */
+	memcpy(lcdw[3].command+5,lines,16);        
+	memcpy(lcdw[4].command+5,lines+16,16);
+	memcpy(lcdw[5].command+5,lines+(16*2),16);
+
+	/* Adjust the buffer numbers */
+	*(lcdw[3].command+4) = 0x20 + 3*(lineno-1);
+	*(lcdw[4].command+4) = 0x21 + 3*(lineno-1);
+	*(lcdw[5].command+4) = 0x22 + 3*(lineno-1);
+
+	/* Adjust flags */
+	if (z > 16) {
+		f |= LCD_LINE_SCROLL | LCD_2_BUFFERS;
+		if (z > 16*2) { f &= 0xF0; f |= LCD_3_BUFFERS; }
+	}
+
+	/* Write the text */
+	lcdw[1].command[4 + lineno] = LCD_LINE_INIT;
+	i = 0; while (lcdw[i].len != 0) { write(sock,lcdw[i].command,lcdw[i].len); i++; } free(lcdw);
 }		
 
 int logitech_mediapad(int sock) {
-	DBusMessage *db_msg, *db_msg_reply; DBusConnection *db_conn = NULL; DBusError db_err; DBusMessageIter db_args; dbus_uint32_t db_u1, db_u2;
+	DBusMessage *db_msg, *db_msg_reply; DBusConnection *db_conn = NULL; DBusError db_err; DBusMessageIter db_args,db_sub; dbus_uint32_t db_u1, db_u2, db_u3;
 	char buf[25], *cwtmp; struct pollfd p; int fd = 0, mode = 0, discard_keyup = 0, prev_key = 0, icons = 0, on_dbus = 0, last_dbus_poll = 0, ln = 0;
 	memset(&p,0,sizeof(struct pollfd)); p.fd = sock; p.events = POLLIN | POLLHUP | POLLERR; 
 
@@ -827,6 +893,60 @@
 						}
 					}
 					dinovo_dbus_do_reply(db_msg);
+				} else if (dbus_message_is_method_call(db_msg,"com.hentenaar.Dinovo.MediaPad","WriteLine")) {
+					/* WriteLine(lineno, text) Max Length: 48 */ 
+					if (dbus_message_iter_init(db_msg,&db_args)) {
+						if (dbus_message_iter_get_arg_type(&db_args) == DBUS_TYPE_UINT32) dbus_message_iter_get_basic(&db_args,&db_u1);
+						if (dbus_message_iter_has_next(&db_args)) {
+							dbus_message_iter_next(&db_args);
+							if (dbus_message_iter_get_arg_type(&db_args) == DBUS_TYPE_STRING) {
+								dbus_message_iter_get_basic(&db_args,&cwtmp);
+								if (cwtmp && strlen(cwtmp) > 0) write_lcd_line(sock,cwtmp,db_u1);
+							}
+						}
+					}
+					dinovo_dbus_do_reply(db_msg);
+				} else if (dbus_message_is_method_call(db_msg,"com.hentenaar.Dinovo.MediaPad","WriteTextBin")) {
+					/* WriteTextBin(chars) Max Length: 144 */ 
+					if (dbus_message_iter_init(db_msg,&db_args)) {
+						if (dbus_message_iter_get_arg_type(&db_args) == DBUS_TYPE_ARRAY) {
+							dbus_message_iter_recurse(&db_args,&db_sub);
+							if ((cwtmp = malloc(1+(16*9)))) {
+								memset(cwtmp,0,1+(16*9));
+								for (db_u1=0;db_u1<=16*9;db_u1++) {
+									dbus_message_iter_get_basic(&db_sub,&db_u2);
+									cwtmp[db_u1] = (char)db_u2;
+									if (dbus_message_iter_has_next(&db_sub)) dbus_message_iter_next(&db_sub);
+									else break;
+								} 
+								if (db_u1 > 0) write_lcd_text(sock,cwtmp); 
+								free(cwtmp);
+							}
+						}
+					}
+					dinovo_dbus_do_reply(db_msg);
+				} else if (dbus_message_is_method_call(db_msg,"com.hentenaar.Dinovo.MediaPad","WriteLineBin")) {
+					/* WriteLineBin(lineno, chars) Max Length: 48 */ 
+					if (dbus_message_iter_init(db_msg,&db_args)) {
+						if (dbus_message_iter_get_arg_type(&db_args) == DBUS_TYPE_UINT32) dbus_message_iter_get_basic(&db_args,&db_u1);
+						if (dbus_message_iter_has_next(&db_args)) {
+							dbus_message_iter_next(&db_args);
+							if (dbus_message_iter_get_arg_type(&db_args) == DBUS_TYPE_ARRAY) {
+								dbus_message_iter_recurse(&db_args,&db_sub);
+								if ((cwtmp = malloc(1+(16*3)))) {
+									memset(cwtmp,0,1+(16*3));
+									for (db_u3=0;db_u3<=16*3;db_u3++) {
+										dbus_message_iter_get_basic(&db_sub,&db_u2);
+										cwtmp[db_u3] = (char)db_u2;
+										if (dbus_message_iter_has_next(&db_sub)) dbus_message_iter_next(&db_sub);
+										else break;
+									} 
+									if (db_u3 > 0) write_lcd_line(sock,cwtmp,db_u1); free(cwtmp);
+								}
+							}
+						}
+					}
+					dinovo_dbus_do_reply(db_msg);
 				} else if (dbus_message_is_method_call(db_msg,"com.hentenaar.Dinovo.MediaPad","SetIndicator")) {
 					/* SetIndicator(indicator, blink) 
 					 *	[ indicator := see LCD_ICON_* above ]
