merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / input / psaux / logips2pp.c
1 /*
2 * Logitech PS/2++ mouse driver
3 *
4 * Copyright (c) 1999-2003 Vojtech Pavlik <vojtech@suse.cz>
5 * Copyright (c) 2003 Eric Wong <eric@yhbt.net>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12 #include <ddk/ntddk.h>
13 #include <ddk/ntddmou.h>
14 #include "mouse.h"
15 #include "logips2pp.h"
16
17 /*
18 * Process a PS2++ or PS2T++ packet.
19 */
20
21 int SendCommand(PDEVICE_EXTENSION DeviceExtension, unsigned char *param, int command);
22 void PS2PPProcessPacket(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input, int *wheel)
23 {
24 unsigned char *packet = DeviceExtension->MouseBuffer;
25
26 if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
27
28 switch ((packet[1] >> 4) | (packet[0] & 0x30)) {
29
30 case 0x0d: /* Mouse extra info */
31
32 /* FIXME - mouse seems to have 2 wheels
33 input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
34 (int) (packet[2] & 8) - (int) (packet[2] & 7)); */
35
36 *wheel = (int)(packet[2] & 8) - (int)(packet[2] & 7);
37 Input->RawButtons |= (((packet[2] >> 4) & 1) ? GPM_B_FOURTH : 0);
38 Input->RawButtons |= (((packet[2] >> 5) & 1) ? GPM_B_FIFTH : 0);
39
40 break;
41
42 case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
43
44 Input->RawButtons |= ((packet[2] & 1) ? GPM_B_FOURTH : 0);
45 Input->RawButtons |= (((packet[2] >> 1) & 1) ? GPM_B_FIFTH : 0);
46
47 /* FIXME - support those buttons???
48 input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1);
49 input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1);
50 input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1);
51 */
52
53 break;
54
55 case 0x0f: /* TouchPad extra info */
56
57 /* FIXME - mouse seems to have 2 wheels
58 input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
59 (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); */
60
61 *wheel = (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7);
62
63 packet[0] = packet[2] | 0x08;
64 break;
65
66 default:
67 DbgPrint("logips2pp.c: Received PS2++ packet 0x%x, but don't know how to handle.\n",
68 (packet[1] >> 4) | (packet[0] & 0x30));
69 }
70
71 packet[0] &= 0x0f;
72 packet[1] = 0;
73 packet[2] = 0;
74
75 }
76 }
77
78 /*
79 * ps2pp_cmd() sends a PS2++ command, sliced into two bit
80 * pieces through the SETRES command. This is needed to send extended
81 * commands to mice on notebooks that try to understand the PS/2 protocol
82 * Ugly.
83 */
84
85 static int ps2pp_cmd(PDEVICE_EXTENSION DeviceExtension, unsigned char *param, unsigned char command)
86 {
87 unsigned char d;
88 int i;
89
90 if (SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11))
91 return -1;
92
93 for (i = 6; i >= 0; i -= 2) {
94 d = (command >> i) & 3;
95 if(SendCommand(DeviceExtension, &d, PSMOUSE_CMD_SETRES))
96 return -1;
97 }
98
99 if (SendCommand(DeviceExtension, param, PSMOUSE_CMD_POLL))
100 return -1;
101
102 return 0;
103 }
104
105 /*
106 * SmartScroll / CruiseControl for some newer Logitech mice Defaults to
107 * enabled if we do nothing to it. Of course I put this in because I want it
108 * disabled :P
109 * 1 - enabled (if previously disabled, also default)
110 * 0/2 - disabled
111 */
112
113 static void ps2pp_set_smartscroll(PDEVICE_EXTENSION DeviceExtension)
114 {
115 unsigned char param[4];
116
117 ps2pp_cmd(DeviceExtension, param, 0x32);
118
119 param[0] = 0;
120 SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
121 SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
122 SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
123
124 if (DeviceExtension->SmartScroll == 1)
125 param[0] = 1;
126 else
127 if (DeviceExtension->SmartScroll > 2)
128 return;
129
130 /* else leave param[0] == 0 to disable */
131 SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
132 }
133
134 /*
135 * Support 800 dpi resolution _only_ if the user wants it (there are good
136 * reasons to not use it even if the mouse supports it, and of course there are
137 * also good reasons to use it, let the user decide).
138 */
139
140 void PS2PPSet800dpi(PDEVICE_EXTENSION DeviceExtension)
141 {
142 unsigned char param = 3;
143 SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
144 SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
145 SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
146 SendCommand(DeviceExtension, &param, PSMOUSE_CMD_SETRES);
147 }
148
149 /*
150 * Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or
151 * touchpad.
152 */
153
154 int PS2PPDetectModel(PDEVICE_EXTENSION DeviceExtension, unsigned char *param)
155 {
156 int i;
157 //char *vendor, *name;
158 static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, 112, -1 };
159 static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
160 76, 80, 81, 83, 88, 96, 97, 112, -1 };
161 static int logitech_mx[] = { 112, -1 };
162
163 //vendor = "Logitech";
164 //DbgPrint("Vendor: %s, name: %s\n", vendor, name);
165 DeviceExtension->MouseModel = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
166
167 /*if (param[1] < 3)
168 clear_bit(BTN_MIDDLE, DeviceExtension->dev.keybit);
169 if (param[1] < 2)
170 clear_bit(BTN_RIGHT, DeviceExtension->dev.keybit);*/
171
172 DeviceExtension->MouseType = PSMOUSE_PS2;
173
174 for (i = 0; logitech_ps2pp[i] != -1; i++)
175 if (logitech_ps2pp[i] == DeviceExtension->MouseModel)
176 DeviceExtension->MouseType = PSMOUSE_PS2PP;
177
178 if (DeviceExtension->MouseType == PSMOUSE_PS2PP) {
179
180 /* for (i = 0; logitech_4btn[i] != -1; i++)
181 if (logitech_4btn[i] == DeviceExtension->MouseModel)
182 set_bit(BTN_SIDE, psmouse->dev.keybit);
183 */
184 for (i = 0; logitech_wheel[i] != -1; i++)
185 if (logitech_wheel[i] == DeviceExtension->MouseModel) {
186 // set_bit(REL_WHEEL, psmouse->dev.relbit);
187 //name = "Wheel Mouse";DbgPrint("Vendor: %s, name: %s\n", vendor, name);
188 }
189
190 for (i = 0; logitech_mx[i] != -1; i++)
191 if (logitech_mx[i] == DeviceExtension->MouseModel) {
192 /* set_bit(BTN_SIDE, psmouse->dev.keybit);
193 set_bit(BTN_EXTRA, psmouse->dev.keybit);
194 set_bit(BTN_BACK, psmouse->dev.keybit);
195 set_bit(BTN_FORWARD, psmouse->dev.keybit);
196 set_bit(BTN_TASK, psmouse->dev.keybit);
197 */ //name = "MX Mouse";DbgPrint("Vendor: %s, name: %s\n", vendor, name);
198 }
199
200 /*
201 * Do Logitech PS2++ / PS2T++ magic init.
202 */
203
204 if (DeviceExtension->MouseModel == 97) { /* TouchPad 3 */
205
206 // set_bit(REL_WHEEL, psmouse->dev.relbit);
207 // set_bit(REL_HWHEEL, psmouse->dev.relbit);
208
209 param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */
210 SendCommand(DeviceExtension, param, 0x30d1);
211 param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */
212 SendCommand(DeviceExtension, param, 0x30d1);
213 param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */
214 SendCommand(DeviceExtension, param, 0x30d1);
215
216 param[0] = 0;
217 if (!SendCommand(DeviceExtension, param, 0x13d1) &&
218 param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
219 //name = "TouchPad 3";DbgPrint("Vendor: %s, name: %s\n", vendor, name);
220 return PSMOUSE_PS2TPP;
221 }
222
223 } else {
224
225 param[0] = param[1] = param[2] = 0;
226 ps2pp_cmd(DeviceExtension, param, 0x39); /* Magic knock */
227 ps2pp_cmd(DeviceExtension, param, 0xDB);
228
229 if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 &&
230 (param[2] & 3) == ((param[1] >> 2) & 3)) {
231 ps2pp_set_smartscroll(DeviceExtension);
232 return PSMOUSE_PS2PP;
233 }
234 }
235 }
236
237 return 0;
238 }
239