Index: uspace/app/wacomdump/wacomdump.c
===================================================================
--- uspace/app/wacomdump/wacomdump.c	(revision 91ecaa1074636a3d3b17808616e1c5a4979a1928)
+++ uspace/app/wacomdump/wacomdump.c	(revision 58a369e7f92c3d79858ae9bb130b6e24080f62f3)
@@ -32,4 +32,5 @@
 #include <loc.h>
 #include <stdio.h>
+#include <macros.h>
 
 #define BUF_SIZE 64
@@ -37,4 +38,5 @@
 #define START_OF_PACKET 128
 #define CONTROL_PACKET 64
+#define TOUCH_EVENT 16
 #define FINGER1 1
 #define FINGER2 2
@@ -70,6 +72,8 @@
 	bool stylus_in_proximity;
 	bool stylus_is_eraser;
-	bool button1_pressed;
-	bool button2_pressed;
+	bool tip_pressed; /* Reported as stylus button 1 */
+	bool button1_pressed; /* Reported as stylus button 2 */
+	bool button2_pressed; /* Reported as stylus button 3 */
+	bool finger1_pressed; /* Reported as touch button 1 */
 
 	/* Session to the serial device */
@@ -186,10 +190,4 @@
 	isdv4_event_init(&event);
 
-/*	size_t dbg_ctr;*/
-/*	printf("Packet: ");*/
-/*	for (dbg_ctr = 0; dbg_ctr < size; dbg_ctr++) {*/
-/*		printf("%02hhx ", packet[dbg_ctr]);*/
-/*	}*/
-/*	printf("\n");*/
 
 	if (size == 5 || size == 7) {
@@ -199,9 +197,8 @@
 		event.y = ((packet[3] & 127) << 7) | (packet[4] & 127);
 		event.source = TOUCH;
-		printf("TOUCH finger finger1=%d x=%u y=%u\n", finger1, event.x, event.y);
 
 		if (!state->stylus_in_proximity) {
-			if (!finger1 && state->button1_pressed) {
-				state->button1_pressed = false;
+			if (!finger1 && state->finger1_pressed) {
+				state->finger1_pressed = false;
 
 				event.type = RELEASE;
@@ -209,6 +206,6 @@
 				state->emit_event_fn(&event);
 			}
-			else if (finger1 && !state->button1_pressed) {
-				state->button1_pressed = true;
+			else if (finger1 && !state->finger1_pressed) {
+				state->finger1_pressed = true;
 
 				event.type = PRESS;
@@ -233,12 +230,8 @@
 		event.pressure = (packet[5] & 127) | ((packet[6] & 7) << 7);
 
-		bool eraser = !tip && button2;
-		printf("STYLUS tip=%d button1=%d button2=%d proximity=%d x=%u y=%u p=%u\n",
-		    tip, button1, button2, proximity, event.x, event.y, event.pressure);
-
 		if (proximity && !state->stylus_in_proximity) {
 			/* Stylus came into proximity */
 			state->stylus_in_proximity = true;
-			state->stylus_is_eraser = eraser;
+			state->stylus_is_eraser = !tip && button2;
 			event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);
 			event.type = PROXIMITY_IN;
@@ -254,21 +247,44 @@
 		else {
 			/* Proximity state didn't change, but we need to check if it is still eraser */
-			if (eraser != state->stylus_is_eraser) {
+			if (state->stylus_is_eraser && !button2) {
 				event.type = PROXIMITY_OUT;
-				event.source = eraser ? STYLUS_TIP : STYLUS_ERASER;
+				event.source = STYLUS_ERASER;
 				state->emit_event_fn(&event);
 				event.type = PROXIMITY_IN;
-				event.source = eraser ? STYLUS_ERASER : STYLUS_TIP;
-				state->emit_event_fn(&event);
-				state->stylus_is_eraser = eraser;
+				event.source = STYLUS_TIP;
+				state->emit_event_fn(&event);
+				state->stylus_is_eraser = false;
+			}
+			else if (!state->stylus_is_eraser && !tip && button2) {
+				event.type = PROXIMITY_OUT;
+				event.source = STYLUS_TIP;
+				state->emit_event_fn(&event);
+				event.type = PROXIMITY_IN;
+				event.source = STYLUS_ERASER;
+				state->emit_event_fn(&event);
+				state->stylus_is_eraser = true;
 			}
 		}
 		
 		if (!state->stylus_is_eraser) {
+			if (tip && !state->tip_pressed) {
+				state->tip_pressed = true;
+				event.type = PRESS;
+				event.source = STYLUS_TIP;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			else if (!tip && state->tip_pressed) {
+				state->tip_pressed = false;
+				event.type = RELEASE;
+				event.source = STYLUS_TIP;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
 			if (button1 && !state->button1_pressed) {
 				state->button1_pressed = true;
 				event.type = PRESS;
 				event.source = STYLUS_TIP;
-				event.button = 1;
+				event.button = 2;
 				state->emit_event_fn(&event);
 			}
@@ -277,5 +293,5 @@
 				event.type = RELEASE;
 				event.source = STYLUS_TIP;
-				event.button = 1;
+				event.button = 2;
 				state->emit_event_fn(&event);
 			}
@@ -284,5 +300,5 @@
 				event.type = PRESS;
 				event.source = STYLUS_TIP;
-				event.button = 2;
+				event.button = 3;
 				state->emit_event_fn(&event);
 			}
@@ -291,15 +307,15 @@
 				event.type = RELEASE;
 				event.source = STYLUS_TIP;
-				event.button = 2;
+				event.button = 3;
 				state->emit_event_fn(&event);
 			}
 			event.type = MOVE;
 			event.source = STYLUS_TIP;
-			event.button = (button1 ? 1 : 0) | (button2 ? 2 : 0);
+			event.button = (tip ? 1: 0) | (button1 ? 2 : 0) | (button2 ? 4 : 0);
 			state->emit_event_fn(&event);
 		}
 		else {
-			if (button1 && !state->button1_pressed) {
-				state->button1_pressed = true;
+			if (tip && !state->tip_pressed) {
+				state->tip_pressed = true;
 				event.type = PRESS;
 				event.source = STYLUS_ERASER;
@@ -307,6 +323,6 @@
 				state->emit_event_fn(&event);
 			}
-			else if (!button1 && state->button1_pressed) {
-				state->button1_pressed = false;
+			else if (!tip && state->tip_pressed) {
+				state->tip_pressed = false;
 				event.type = RELEASE;
 				event.source = STYLUS_ERASER;
@@ -316,9 +332,7 @@
 			event.type = MOVE;
 			event.source = STYLUS_ERASER;
-			event.button = (button1 ? 1 : 0);
+			event.button = (tip ? 1 : 0);
 			state->emit_event_fn(&event);
 		}
-		//int xtilt = (packet[8] & 127);
-		//int ytilt = (packet[7] & 127);
 	}
 
@@ -414,6 +428,7 @@
 {
 	bool reading = true;
-	bool silence = true;
+	size_t packet_remaining = 1;
 	while (reading) {
+		if (packet_remaining == 0) packet_remaining = 1;
 		ssize_t read = char_dev_read(state->sess, state->buf + state->buf_end,
 		    state->buf_size - state->buf_end);
@@ -424,13 +439,4 @@
 		state->buf_end += read;
 		
-		if (!silence && read == 0) {
-			silence = true;
-			usleep(100000); /* 100 ms */
-			continue;
-		}
-		else if (read > 0) {
-			silence = false;
-		}
-		
 		size_t i = 0;
 		
@@ -444,11 +450,27 @@
 		/* Process packets one by one */
 		while (reading && i < state->buf_end) {
-			/* Find a start of next packet */
+			/* Determine the packet length */
+			if (state->buf[i] & CONTROL_PACKET) {
+				packet_remaining = 11;
+			}
+			else if (state->buf[i] & TOUCH_EVENT) {
+				packet_remaining = 5;
+			}
+			else {
+				packet_remaining = 9;
+			}
+			
+			/* Find the end of the packet */
 			i++; /* We need to skip the first byte with START_OF_PACKET set */
-			while (i < state->buf_end && (state->buf[i] & START_OF_PACKET) == 0) i++;
+			packet_remaining--; 
+			while (packet_remaining > 0 && i < state->buf_end &&
+			    (state->buf[i] & START_OF_PACKET) == 0) {
+				i++;
+				packet_remaining--;
+			}
 			end = i;
 			
 			/* If we have whole packet, process it */
-			if (end > start && (end != state->buf_end || read == 0)) {
+			if (end > start && packet_remaining == 0) {
 				reading = consumer(state->buf + start, end - start, state);
 				start = end;
@@ -487,5 +509,5 @@
 	write_command(state->sess, CMD_STOP);
 	usleep(250000); /* 250 ms */
-	while (char_dev_read(state->sess, state->buf, state->buf_size) > 0);
+	// FIXME: Read all possible garbage before sending commands
 	write_command(state->sess, CMD_QUERY_STYLUS);
 	read_packets(state, parse_response_stylus);
