xref: /reactos/drivers/input/i8042prt/ps2pp.c (revision 845faec4)
1 /*
2  * PROJECT:     ReactOS i8042 (ps/2 keyboard-mouse controller) driver
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        drivers/input/i8042prt/ps2pp.c
5  * PURPOSE:     ps2pp protocol handling
6  * PROGRAMMERS: Copyright Martijn Vernooij (o112w8r02@sneakemail.com)
7  *              Copyright 2006-2007 Herv� Poussineau (hpoussin@reactos.org)
8  */
9 
10 /* INCLUDES ****************************************************************/
11 
12 #include "i8042prt.h"
13 
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 VOID
19 i8042MouHandlePs2pp(
20 	IN PI8042_MOUSE_EXTENSION DeviceExtension,
21 	IN UCHAR Input)
22 {
23 	UCHAR PktType;
24 	PMOUSE_INPUT_DATA MouseInput;
25 
26 	MouseInput = DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer;
27 
28 	/* First, collect 3 bytes for a packet
29 	 * We can detect out-of-sync only by checking
30 	 * the whole packet anyway.
31 	 *
32 	 * If bit 7 and 8 of the first byte are 0, its
33 	 * a normal packet.
34 	 *
35 	 * Otherwise, the packet is different, like this:
36 	 * 1: E  1 b3 b2  1  x  x  x
37 	 * 2: x  x b1 b0 x1 x0  1  0
38 	 * 3: x  x  x  x  x  x x1 x0
39 	 *
40 	 * b3-0 form a code that specifies the packet type:
41 	 *
42 	 * 0  Device Type
43 	 * 1  Rollers and buttons
44 	 * 2   Reserved
45 	 * 3   Reserved
46 	 * 4  Device ID
47 	 * 5  Channel & Battery
48 	 * 6  Wireless notifications
49 	 * 7   Reserved
50 	 * 8  ShortID LSB (ShortID is a number that is supposed to differentiate
51 	 * 9  ShortID MSB  between your mouse and your neighbours')
52 	 * 10  Reserved
53 	 * 11 Mouse capabilities
54 	 * 12 Remote control LSB
55 	 * 13 Remote control MSB
56 	 * 14  Reserved
57 	 * 15 Extended packet
58 	 */
59 
60 	switch (DeviceExtension->MouseState)
61 	{
62 		case MouseIdle:
63 		case XMovement:
64 			DeviceExtension->MouseLogiBuffer[DeviceExtension->MouseState] = Input;
65 			DeviceExtension->MouseState++;
66 			break;
67 
68 		case YMovement:
69 			DeviceExtension->MouseLogiBuffer[2] = Input;
70 			DeviceExtension->MouseState = MouseIdle;
71 
72 			/* first check if it's a normal packet */
73 
74 			if (!(DeviceExtension->MouseLogiBuffer[0] & 0xC0))
75 			{
76 				DeviceExtension->MouseState = MouseIdle;
77 				i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[0]);
78 				i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[1]);
79 				i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[2]);
80 				/* We could care about wether MouseState really
81 				 * advances, but we don't need to because we're
82 				 * only doing three bytes anyway, so the packet
83 				 * will never complete if it's broken.
84 				 */
85 				return;
86 			}
87 
88 			/* sanity check */
89 			if (((DeviceExtension->MouseLogiBuffer[0] & 0x48) != 0x48) ||
90 			   (((DeviceExtension->MouseLogiBuffer[1] & 0x0C) >> 2) !=
91 			     (DeviceExtension->MouseLogiBuffer[2] & 0x03)))
92 				{
93 					WARN_(I8042PRT, "Ps2pp packet fails sanity checks\n");
94 					return;
95 				}
96 
97 			/* Now get the packet type */
98 			PktType = ((DeviceExtension->MouseLogiBuffer[0] & 0x30) >> 2) |
99 			          ((DeviceExtension->MouseLogiBuffer[1] & 0x30) >> 4);
100 
101 			switch (PktType)
102 			{
103 				case 0:
104 					/* The packet contains the device ID, but we
105 					 * already read that in the initialization
106 					 * sequence. Ignore it.
107 					 */
108 					return;
109 				case 1:
110 					RtlZeroMemory(MouseInput, sizeof(MOUSE_INPUT_DATA));
111 					if (DeviceExtension->MouseLogiBuffer[2] & 0x10)
112 						MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN;
113 
114 					if (DeviceExtension->MouseLogiBuffer[2] & 0x20)
115 						MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN;
116 
117 					if (DeviceExtension->MouseLogiBuffer[2] & 0x0F)
118 					{
119 						MouseInput->ButtonFlags |= MOUSE_WHEEL;
120 						if (DeviceExtension->MouseLogiBuffer[2] & 0x08)
121 							MouseInput->ButtonData = (DeviceExtension->MouseLogiBuffer[2] & 0x07) - 8;
122 						else
123 							MouseInput->ButtonData = DeviceExtension->MouseLogiBuffer[2] & 0x07;
124 					}
125 					i8042MouHandleButtons(
126 						DeviceExtension,
127 						MOUSE_BUTTON_4_DOWN | MOUSE_BUTTON_5_DOWN);
128 					DeviceExtension->MouseHook.QueueMousePacket(DeviceExtension->MouseHook.CallContext);
129 					return;
130 				default:
131 					/* These are for things that would probably
132 					 * be handled by logitechs own driver.
133 					 */
134 					return;
135 			}
136 
137 		default:
138 			WARN_(I8042PRT, "Unexpected input state for ps2pp!\n");
139 	}
140 }
141