Index: console/console.c
===================================================================
--- console/console.c	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ console/console.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -299,4 +299,7 @@
 			/* TODO: Handle hangup */
 			return;
+		case KBD_MS_MOVE:
+			gcons_mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			break;
 		case KBD_PUSHCHAR:
 			/* got key from keyboard driver */
Index: console/gcons.c
===================================================================
--- console/gcons.c	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ console/gcons.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -231,4 +231,26 @@
 }
 
+
+static inline int limit(int a,int left, int right)
+{
+	if (a < left)
+		a = left;
+	if (a >= right)
+		a = right - 1;
+	return a;
+}
+
+void gcons_mouse_move(int dx, int dy)
+{
+	static int x = 0;
+	static int y = 0;
+
+	x = limit(x+dx, 0, xres);
+	y = limit(y+dy, 0, yres);
+
+	async_msg_2(fbphone, FB_POINTER_MOVE, x, y);
+}
+
+
 /** Draw a PPM pixmap to framebuffer
  *
Index: console/gcons.h
===================================================================
--- console/gcons.h	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ console/gcons.h	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -42,4 +42,5 @@
 void gcons_notify_connect(int consnum);
 void gcons_notify_disconnect(int consnum);
+void gcons_mouse_move(int dx, int dy);
 
 #endif
Index: fb/fb.c
===================================================================
--- fb/fb.c	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ fb/fb.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -1125,4 +1125,8 @@
 			ipc_answer_fast(callid, 0, screen.xres,screen.yres);
 			continue;
+		case FB_POINTER_MOVE:
+			putpixel(&viewports[0], IPC_GET_ARG1(call), IPC_GET_ARG2(call),
+				 0xd0a080);
+			break;
 		default:
 			retval = ENOENT;
Index: kbd/Makefile
===================================================================
--- kbd/Makefile	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ kbd/Makefile	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -49,4 +49,15 @@
 	arch/$(ARCH)/src/kbd.c
 
+ifeq ($(ARCH), ia32)
+	ARCH_SOURCES += arch/$(ARCH)/src/mouse.c
+	CFLAGS += -DMOUSE_ENABLED
+endif
+ifeq ($(ARCH), amd64)
+	ARCH_SOURCES += arch/$(ARCH)/src/mouse.c
+	CFLAGS += -DMOUSE_ENABLED
+endif
+
+
+
 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
 ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
Index: kbd/arch/ia32/src/kbd.c
===================================================================
--- kbd/arch/ia32/src/kbd.c	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ kbd/arch/ia32/src/kbd.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -450,15 +450,14 @@
 	int status = IPC_GET_ARG1(*call);
 
-	if ((status & i8042_MOUSE_DATA)) {
-		;
-	} else {
-		int scan_code = IPC_GET_ARG2(*call);
-		
-		if (scan_code != IGNORE_CODE) {
-			if (scan_code & KEY_RELEASE)
-				key_released(keybuffer, scan_code ^ KEY_RELEASE);
-			else
-				key_pressed(keybuffer, scan_code);
-		}
+	if ((status & i8042_MOUSE_DATA))
+		return 0;
+	
+	int scan_code = IPC_GET_ARG2(*call);
+	
+	if (scan_code != IGNORE_CODE) {
+		if (scan_code & KEY_RELEASE)
+			key_released(keybuffer, scan_code ^ KEY_RELEASE);
+		else
+			key_pressed(keybuffer, scan_code);
 	}
 	return 	1;
Index: kbd/arch/ia32/src/mouse.c
===================================================================
--- kbd/arch/ia32/src/mouse.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
+++ kbd/arch/ia32/src/mouse.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ipc/ipc.h>
+#include <async.h>
+#include <kbd.h>
+#include <keys.h>
+
+#define i8042_MOUSE_DATA   0x20
+
+#define BUFSIZE 3
+
+typedef struct {
+	union {
+		unsigned char data[BUFSIZE];
+		struct {
+			unsigned leftbtn : 1;
+			unsigned rightbtn : 1;
+			unsigned middlebtn : 1;
+			unsigned isone : 1; /* Always one */
+			unsigned xsign : 1;
+			unsigned ysign : 1;
+			unsigned xovfl : 1;
+			unsigned yovfl : 1;
+			unsigned char x;
+			unsigned char y;
+		} val;
+	}u;
+}ps2packet_t;
+
+static ps2packet_t buf;
+static int bufpos = 0;
+static int leftbtn = 0;
+static int rightbtn = 0;
+static int middlebtn = 0;
+
+/** Convert 9-bit 2-complement signed number to integer */
+static int bit9toint(int sign, unsigned char data)
+{
+	int tmp;
+
+	if (!sign)
+		return data;
+
+	tmp = ((unsigned char)~data) + 1;
+	return -tmp;
+}
+
+/** Process mouse data
+ *
+ * @return True if mouse command was recognized and processed
+ */
+int mouse_arch_process(int phoneid, ipc_call_t *call)
+{
+	int status = IPC_GET_ARG1(*call);
+	int data = IPC_GET_ARG2(*call);
+	int x,y;
+
+	if (!(status & i8042_MOUSE_DATA))
+		return 0;
+
+	/* Check that we have not lost synchronization */
+	if (bufpos == 0 && !(data & 0x8))
+		return 1; /* Synchro lost, ignore byte */
+
+	buf.u.data[bufpos++] = data;
+	if (bufpos == BUFSIZE) {
+		bufpos = 0;
+		if (phoneid != -1) {
+			if (buf.u.val.leftbtn ^ leftbtn) {
+				leftbtn = buf.u.val.leftbtn;
+				async_msg(phoneid, KBD_MS_LEFT, leftbtn);
+			}
+			if (buf.u.val.rightbtn & rightbtn) {
+				rightbtn = buf.u.val.middlebtn;
+				async_msg(phoneid, KBD_MS_RIGHT, rightbtn);
+			}
+			if (buf.u.val.rightbtn & rightbtn) {
+				middlebtn = buf.u.val.middlebtn;
+				async_msg(phoneid, KBD_MS_MIDDLE, middlebtn);
+			}
+			x = bit9toint(buf.u.val.xsign, buf.u.val.x);
+			y = bit9toint(buf.u.val.ysign, buf.u.val.y);
+			if (x || y)
+				async_msg_2(phoneid, KBD_MS_MOVE, (ipcarg_t)x, (ipcarg_t)(-y));
+		}
+	}
+
+	
+	return 1;
+}
Index: kbd/generic/kbd.c
===================================================================
--- kbd/generic/kbd.c	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ kbd/generic/kbd.c	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -65,8 +65,13 @@
 	int chr;
 
+#ifdef MOUSE_ENABLED
+	if (mouse_arch_process(phone2cons, call))
+		return;
+#endif
+	
+	kbd_arch_process(&keybuffer, call);
+
 	if (cons_connected && phone2cons != -1) {
 		/* recode to ASCII - one interrupt can produce more than one code so result is stored in fifo */
-		kbd_arch_process(&keybuffer, call);
-		
 		while (!keybuffer_empty(&keybuffer)) {
 			if (!keybuffer_pop(&keybuffer, (int *)&chr))
Index: kbd/include/kbd.h
===================================================================
--- kbd/include/kbd.h	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ kbd/include/kbd.h	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -38,6 +38,8 @@
 #define __KBD_H__
 
+#include <key_buffer.h>
 
 int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call);
+int mouse_arch_process(int phoneid, ipc_call_t *call);
 
 #endif
Index: kbd/include/keys.h
===================================================================
--- kbd/include/keys.h	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ kbd/include/keys.h	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -38,5 +38,9 @@
 #define _KBD_KEYS_H_
 
-#define KBD_PUSHCHAR 1024
+#define KBD_PUSHCHAR    1024
+#define KBD_MS_LEFT     1025
+#define KBD_MS_RIGHT    1026
+#define KBD_MS_MIDDLE   1027
+#define KBD_MS_MOVE     1028
 
 #define KBD_KEY_F1	0x3b
Index: libc/include/ipc/fb.h
===================================================================
--- libc/include/ipc/fb.h	(revision 7a0c530583bbccd907665710e02f988580737221)
+++ libc/include/ipc/fb.h	(revision 830ac99c5d89bf27e84afd093c91647ea13a76a0)
@@ -71,4 +71,6 @@
 #define FB_ANIM_STOP         1205
 
+#define FB_POINTER_MOVE      1300
+
 #endif
 
