2 * Logitech PS/2++ mouse driver
4 * Copyright (c) 1999-2003 Vojtech Pavlik <vojtech@suse.cz>
5 * Copyright (c) 2003 Eric Wong <eric@yhbt.net>
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.
12 #include <ddk/ntddk.h>
13 #include <ddk/ntddmou.h>
15 #include "logips2pp.h"
18 * Process a PS2++ or PS2T++ packet.
21 int SendCommand(PDEVICE_EXTENSION DeviceExtension
, unsigned char *param
, int command
);
22 void PS2PPProcessPacket(PDEVICE_EXTENSION DeviceExtension
, PMOUSE_INPUT_DATA Input
, int *wheel
)
24 unsigned char *packet
= DeviceExtension
->MouseBuffer
;
26 if ((packet
[0] & 0x48) == 0x48 && (packet
[1] & 0x02) == 0x02) {
28 switch ((packet
[1] >> 4) | (packet
[0] & 0x30)) {
30 case 0x0d: /* Mouse extra info */
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)); */
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);
42 case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
44 Input
->RawButtons
|= ((packet
[2] & 1) ? GPM_B_FOURTH
: 0);
45 Input
->RawButtons
|= (((packet
[2] >> 1) & 1) ? GPM_B_FIFTH
: 0);
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);
55 case 0x0f: /* TouchPad extra info */
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)); */
61 *wheel
= (int) ((packet
[2] >> 4) & 8) - (int) ((packet
[2] >> 4) & 7);
63 packet
[0] = packet
[2] | 0x08;
67 DbgPrint("logips2pp.c: Received PS2++ packet 0x%x, but don't know how to handle.\n",
68 (packet
[1] >> 4) | (packet
[0] & 0x30));
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
85 static int ps2pp_cmd(PDEVICE_EXTENSION DeviceExtension
, unsigned char *param
, unsigned char command
)
90 if (SendCommand(DeviceExtension
, NULL
, PSMOUSE_CMD_SETSCALE11
))
93 for (i
= 6; i
>= 0; i
-= 2) {
94 d
= (command
>> i
) & 3;
95 if(SendCommand(DeviceExtension
, &d
, PSMOUSE_CMD_SETRES
))
99 if (SendCommand(DeviceExtension
, param
, PSMOUSE_CMD_POLL
))
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
109 * 1 - enabled (if previously disabled, also default)
113 static void ps2pp_set_smartscroll(PDEVICE_EXTENSION DeviceExtension
)
115 unsigned char param
[4];
117 ps2pp_cmd(DeviceExtension
, param
, 0x32);
120 SendCommand(DeviceExtension
, param
, PSMOUSE_CMD_SETRES
);
121 SendCommand(DeviceExtension
, param
, PSMOUSE_CMD_SETRES
);
122 SendCommand(DeviceExtension
, param
, PSMOUSE_CMD_SETRES
);
124 if (DeviceExtension
->SmartScroll
== 1)
127 if (DeviceExtension
->SmartScroll
> 2)
130 /* else leave param[0] == 0 to disable */
131 SendCommand(DeviceExtension
, param
, PSMOUSE_CMD_SETRES
);
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).
140 void PS2PPSet800dpi(PDEVICE_EXTENSION DeviceExtension
)
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
, ¶m
, PSMOUSE_CMD_SETRES
);
150 * Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or
154 int PS2PPDetectModel(PDEVICE_EXTENSION DeviceExtension
, unsigned char *param
)
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 };
163 //vendor = "Logitech";
164 //DbgPrint("Vendor: %s, name: %s\n", vendor, name);
165 DeviceExtension
->MouseModel
= ((param
[0] >> 4) & 0x07) | ((param
[0] << 3) & 0x78);
168 clear_bit(BTN_MIDDLE, DeviceExtension->dev.keybit);
170 clear_bit(BTN_RIGHT, DeviceExtension->dev.keybit);*/
172 DeviceExtension
->MouseType
= PSMOUSE_PS2
;
174 for (i
= 0; logitech_ps2pp
[i
] != -1; i
++)
175 if (logitech_ps2pp
[i
] == DeviceExtension
->MouseModel
)
176 DeviceExtension
->MouseType
= PSMOUSE_PS2PP
;
178 if (DeviceExtension
->MouseType
== PSMOUSE_PS2PP
) {
180 /* for (i = 0; logitech_4btn[i] != -1; i++)
181 if (logitech_4btn[i] == DeviceExtension->MouseModel)
182 set_bit(BTN_SIDE, psmouse->dev.keybit);
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);
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);
201 * Do Logitech PS2++ / PS2T++ magic init.
204 if (DeviceExtension
->MouseModel
== 97) { /* TouchPad 3 */
206 // set_bit(REL_WHEEL, psmouse->dev.relbit);
207 // set_bit(REL_HWHEEL, psmouse->dev.relbit);
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);
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
;
225 param
[0] = param
[1] = param
[2] = 0;
226 ps2pp_cmd(DeviceExtension
, param
, 0x39); /* Magic knock */
227 ps2pp_cmd(DeviceExtension
, param
, 0xDB);
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
;