Implement mouse packet timeout. Fixes right-click menu appearing incorrectly on qemu if debuggins is used. Patch by Tinus
Modified: trunk/reactos/drivers/input/i8042prt/i8042prt.h
Modified: trunk/reactos/drivers/input/i8042prt/mouse.c

Modified: trunk/reactos/drivers/input/i8042prt/i8042prt.h
--- trunk/reactos/drivers/input/i8042prt/i8042prt.h	2005-05-17 20:43:27 UTC (rev 15388)
+++ trunk/reactos/drivers/input/i8042prt/i8042prt.h	2005-05-17 20:51:39 UTC (rev 15389)
@@ -86,7 +86,7 @@
 	DWORD OverrideKeyboardType;
 	DWORD OverrideKeyboardSubtype;
 	DWORD MouseResendStallTime;
-	DWORD MouseSynchIn100ns;
+	DWORD MouseSynchIn100ns;      /* done */
 	DWORD MouseResolution;        /* done */
 	DWORD NumberOfButtons;
 	DWORD EnableWheelDetection;
@@ -169,6 +169,7 @@
 	MOUSE_INPUT_DATA *MouseBuffer;
 	ULONG MouseInBuffer;
 	USHORT MouseButtonState;
+	ULARGE_INTEGER MousePacketStartTime;
 
 	UCHAR MouseLogiBuffer[3];
 	UCHAR MouseLogitechID;

Modified: trunk/reactos/drivers/input/i8042prt/mouse.c
--- trunk/reactos/drivers/input/i8042prt/mouse.c	2005-05-17 20:43:27 UTC (rev 15388)
+++ trunk/reactos/drivers/input/i8042prt/mouse.c	2005-05-17 20:51:39 UTC (rev 15389)
@@ -45,6 +45,39 @@
 	                           WaitForAck);
 }
 
+/* Test if packets are taking too long to come in. If they do, we
+ * might have gotten out of sync and should just drop what we have.
+ *
+ * If we want to be totally right, we'd also have to keep a count of
+ * errors, and totally reset the mouse after too much of them (can
+ * happen if the user is using a KVM switch and an OS on another port
+ * resets the mouse, or if the user hotplugs the mouse, or if we're just
+ * generally unlucky). Also note the input parsing routine where we
+ * drop invalid input packets.
+ */
+static VOID STDCALL I8042MouseInputTestTimeout(PDEVICE_EXTENSION DevExt)
+{
+	ULARGE_INTEGER Now;
+
+	if (DevExt->MouseState == MouseExpectingACK ||
+	    DevExt->MouseState == MouseResetting)
+		return;
+
+	Now.QuadPart = KeQueryInterruptTime();
+
+	if (DevExt->MouseState != MouseIdle) {
+		/* Check if the last byte came too long ago */
+		if (Now.QuadPart - DevExt->MousePacketStartTime.QuadPart >
+		                           DevExt->Settings.MouseSynchIn100ns) {
+			DPRINT1("Mouse input packet timeout\n");
+			DevExt->MouseState = MouseIdle;
+		}
+	}
+
+	if (DevExt->MouseState == MouseIdle)
+		DevExt->MousePacketStartTime.QuadPart = Now.QuadPart;
+}
+
 /*
  * Call the customization hook. The Ret2 parameter is about wether
  * we should go on with the interrupt. The return value is what
@@ -517,6 +550,8 @@
 		return TRUE;
 	}
 
+	I8042MouseInputTestTimeout(DevExt);
+
 	if (I8042MouseResetIsr(DevExt, PortStatus, &Output)) {
 		DPRINT("Handled by ResetIsr or hooked Isr\n");
 		if (NoChange != DevExt->MouseTimeoutState) {