diff --git a/headers/os/drivers/usb/USB_hid_page_digitizers.h b/headers/os/drivers/usb/USB_hid_page_digitizers.h
index 1bfc9ba..66460a8 100644
--- a/headers/os/drivers/usb/USB_hid_page_digitizers.h
+++ b/headers/os/drivers/usb/USB_hid_page_digitizers.h
@@ -54,7 +54,9 @@ enum {
 	B_HID_UID_DIG_SECONDARY_TIP_SWITCH,
 	B_HID_UID_DIG_BARREL_SWITCH,
 	B_HID_UID_DIG_ERASER,
-	B_HID_UID_DIG_TABLET_PICK
+	B_HID_UID_DIG_TABLET_PICK,
+	B_HID_UID_DIG_CONFIDENCE,
+	B_HID_UID_DIG_CONTACT_IDENTIFIER = 0x51,
 };
 
 
diff --git a/headers/private/input/keyboard_mouse_driver.h b/headers/private/input/keyboard_mouse_driver.h
index 99306fd..5eab743 100644
--- a/headers/private/input/keyboard_mouse_driver.h
+++ b/headers/private/input/keyboard_mouse_driver.h
@@ -111,6 +111,7 @@ typedef struct {
 	int32		wheel_xdelta;
 	float		tilt_x;
 	float		tilt_y;
+	uint32		contact_id;
 } tablet_movement;
 
 
diff --git a/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp b/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp
index 283231a..2e20997 100644
--- a/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp
+++ b/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp
@@ -33,7 +33,7 @@
 
 
 #undef TRACE
-//#define TRACE_TABLET_DEVICE
+// #define TRACE_TABLET_DEVICE
 #ifdef TRACE_TABLET_DEVICE
 
 	class FunctionTracer {
@@ -289,13 +289,16 @@ TabletDevice::_ControlThread()
 	}
 
 	_UpdateSettings();
-
+	
+	struct {
+		uint32 buttons;
+		float xpos, ypos;
+	} trackingState[4];
+	memset(&trackingState, 0, sizeof(trackingState));
+	
 	static const bigtime_t kTransferDelay = 1000000 / 125;
 		// 125 transfers per second should be more than enough
 	bigtime_t nextTransferTime = system_time() + kTransferDelay;
-	uint32 lastButtons = 0;
-	float lastXPosition = 0;
-	float lastYPosition = 0;
 
 	while (fActive) {
 		tablet_movement movements;
@@ -309,6 +312,9 @@ TabletDevice::_ControlThread()
 			return;
 		}
 
+		if (movements.contact_id >= 4)
+			continue;
+
 		// take care of updating the settings first, if necessary
 		if (fUpdateSettings) {
 			fUpdateSettings = false;
@@ -324,7 +330,31 @@ TabletDevice::_ControlThread()
 
 		// Send single messages for each event
 
-		uint32 buttons = lastButtons ^ movements.buttons;
+		if (movements.xpos != trackingState[movements.contact_id].xpos
+			|| movements.ypos != trackingState[movements.contact_id].ypos) {
+			BMessage* message = _BuildMouseMessage(B_MOUSE_MOVED,
+				movements.timestamp, trackingState[movements.contact_id].buttons, movements.xpos,
+				movements.ypos);
+			if (message != NULL) {
+				message->AddFloat("be:tablet_x", movements.xpos);
+				message->AddFloat("be:tablet_y", movements.ypos);
+				message->AddFloat("be:tablet_pressure", movements.pressure);
+				message->AddInt32("be:tablet_eraser", movements.eraser);
+				if (movements.tilt_x != 0.0 || movements.tilt_y != 0.0) {
+					message->AddFloat("be:tablet_tilt_x", movements.tilt_x);
+					message->AddFloat("be:tablet_tilt_y", movements.tilt_y);
+				}
+				
+				if (movements.contact_id != 0)
+					message->AddInt32("be:tablet_contact_id", movements.contact_id);
+
+				fTarget.EnqueueMessage(message);
+				trackingState[movements.contact_id].xpos = movements.xpos;
+				trackingState[movements.contact_id].ypos = movements.ypos;
+			}
+		}
+
+		uint32 buttons = trackingState[movements.contact_id].buttons ^ movements.buttons;
 		if (buttons != 0) {
 			bool pressedButton = (buttons & movements.buttons) > 0;
 			BMessage* message = _BuildMouseMessage(
@@ -339,28 +369,7 @@ TabletDevice::_ControlThread()
 					LOG_EVENT("B_MOUSE_UP\n");
 
 				fTarget.EnqueueMessage(message);
-				lastButtons = movements.buttons;
-			}
-		}
-
-		if (movements.xpos != lastXPosition
-			|| movements.ypos != lastYPosition) {
-			BMessage* message = _BuildMouseMessage(B_MOUSE_MOVED,
-				movements.timestamp, movements.buttons, movements.xpos,
-				movements.ypos);
-			if (message != NULL) {
-				message->AddFloat("be:tablet_x", movements.xpos);
-				message->AddFloat("be:tablet_y", movements.ypos);
-				message->AddFloat("be:tablet_pressure", movements.pressure);
-				message->AddInt32("be:tablet_eraser", movements.eraser);
-				if (movements.tilt_x != 0.0 || movements.tilt_y != 0.0) {
-					message->AddFloat("be:tablet_tilt_x", movements.tilt_x);
-					message->AddFloat("be:tablet_tilt_y", movements.tilt_y);
-				}
-
-				fTarget.EnqueueMessage(message);
-				lastXPosition = movements.xpos;
-				lastYPosition = movements.ypos;
+				trackingState[movements.contact_id].buttons = movements.buttons;
 			}
 		}
 
diff --git a/src/add-ons/kernel/drivers/input/usb_hid/Driver.h b/src/add-ons/kernel/drivers/input/usb_hid/Driver.h
index 3b7528e..e857d3c 100644
--- a/src/add-ons/kernel/drivers/input/usb_hid/Driver.h
+++ b/src/add-ons/kernel/drivers/input/usb_hid/Driver.h
@@ -34,7 +34,7 @@ const char **	publish_devices();
 device_hooks *	find_device(const char *name);
 }
 
-#define	TRACE(x...)			/*dprintf(DRIVER_NAME ": " x)*/
+#define	TRACE(x...)			// dprintf(DRIVER_NAME ": " x)
 #define TRACE_ALWAYS(x...)	dprintf(DRIVER_NAME ": " x)
 
 #endif //_USB_HID_DRIVER_H_
diff --git a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp
index 0ba0680..c9238e8 100644
--- a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp
+++ b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp
@@ -53,7 +53,19 @@ MouseProtocolHandler::MouseProtocolHandler(HIDReport &report, bool tablet,
 
 	fWheel = report.FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP,
 		B_HID_UID_GD_WHEEL);
+	
+	fTipSwitch = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
+		B_HID_UID_DIG_TIP_SWITCH);
 
+	fInRange = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
+		B_HID_UID_DIG_IN_RANGE);
+
+	fContactId = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
+		B_HID_UID_DIG_CONTACT_IDENTIFIER);
+
+	fConfidence = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
+		B_HID_UID_DIG_CONFIDENCE);
+	
 	TRACE("mouse device with %lu buttons and %swheel\n", buttonCount,
 		fWheel == NULL ? "no " : "");
 	TRACE("report id: %u\n", report.ID());
@@ -127,7 +139,11 @@ MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection,
 
 		if (!xAxis->Relative() && !yAxis->Relative())
 			tablet = true;
-
+		
+		/* W500 hack */
+		if (tablet && (inputReport->ID() != 4))
+			continue;
+		
 		ProtocolHandler *newHandler = new(std::nothrow) MouseProtocolHandler(
 			*inputReport, tablet, *xAxis, *yAxis);
 		if (newHandler == NULL) {
@@ -223,15 +239,40 @@ MouseProtocolHandler::_ReadReport(void *buffer)
 		wheelData = fWheel->Data();
 
 	uint32 buttons = 0;
-	for (uint32 i = 0; i < B_MAX_MOUSE_BUTTONS; i++) {
-		HIDReportItem *button = fButtons[i];
-		if (button == NULL)
-			break;
+	uint32 tipSwitchData, inRangeData, contactIdData, confidenceData;
 
-		if (button->Extract() == B_OK && button->Valid())
-			buttons |= (button->Data() & 1) << (button->UsageID() - 1);
+	if (fTablet) {
+		if (fTipSwitch != NULL && fTipSwitch->Extract() == B_OK && fTipSwitch->Valid())
+			tipSwitchData = fTipSwitch->Data();
+			
+		if (fInRange != NULL && fInRange->Extract() == B_OK && fInRange->Valid())
+			inRangeData = fInRange->Data();
+		
+		if (fContactId != NULL && fContactId->Extract() == B_OK && fContactId->Valid())
+			contactIdData = fContactId->Data();
+
+		if (fConfidence != NULL && fConfidence->Extract() == B_OK && fConfidence->Valid())
+			confidenceData = fConfidence->Data();
+		
+		TRACE("tipSwitch = %ld, inRange = %ld, contactId = %ld, confidence = %ld\n", tipSwitchData, inRangeData, contactIdData, confidenceData);
+		
+		if (tipSwitchData != 0)
+			buttons = 1;
+		else
+			buttons = 0;
+		
+	} else {
+		for (uint32 i = 0; i < B_MAX_MOUSE_BUTTONS; i++) {
+			HIDReportItem *button = fButtons[i];
+			if (button == NULL)
+				break;
+	
+			if (button->Extract() == B_OK && button->Valid())
+				buttons |= (button->Data() & 1) << (button->UsageID() - 1);
+		}
 	}
-
+	
+	
 	fReport.DoneProcessing();
 	TRACE("got mouse report\n");
 
@@ -257,7 +298,7 @@ MouseProtocolHandler::_ReadReport(void *buffer)
 
 		info->xpos = axisAbsoluteData[0];
 		info->ypos = axisAbsoluteData[1];
-		info->has_contact = true;
+		info->has_contact = buttons & 0x1;
 		info->pressure = 1.0;
 		info->eraser = false;
 		info->tilt_x = 0.0;
@@ -267,6 +308,8 @@ MouseProtocolHandler::_ReadReport(void *buffer)
 		info->clicks = clicks;
 		info->timestamp = timestamp;
 		info->wheel_ydelta = -wheelData;
+		
+		info->contact_id = contactIdData;
 	} else {
 		mouse_movement *info = (mouse_movement *)buffer;
 		memset(info, 0, sizeof(mouse_movement));
diff --git a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h
index ec6121b..b14665e 100644
--- a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h
+++ b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h
@@ -43,6 +43,10 @@ private:
 			HIDReportItem &		fYAxis;
 			HIDReportItem *		fWheel;
 			HIDReportItem *		fButtons[B_MAX_MOUSE_BUTTONS];
+			HIDReportItem * 	fTipSwitch;
+			HIDReportItem * 	fInRange;
+			HIDReportItem * 	fContactId;
+			HIDReportItem * 	fConfidence;
 
 			uint32				fLastButtons;
 			uint32				fClickCount;
