ReactOS 0.4.15-dev-7788-g1ad9096
mouse.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/hardware/mouse.c
5 * PURPOSE: PS/2 Mouse emulation
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include "ntvdm.h"
12
13#define NDEBUG
14#include <debug.h>
15
16#include "mouse.h"
17#include "ps2.h"
18
19#include "clock.h"
20#include "video/svga.h"
21
22#include "../console/video.h"
23
24
25/* PRIVATE VARIABLES **********************************************************/
26
27static const BYTE ScrollMagic[3] = { 200, 100, 80 };
28static const BYTE ExtraButtonMagic[3] = { 200, 200, 80 };
29
35static BYTE Resolution; /* Completely ignored */
36static BOOLEAN Scaling; /* Completely ignored */
46
47static UINT MouseCycles = 10;
48
49static BYTE MousePS2Port = 1;
50
51/* PUBLIC VARIABLES ***********************************************************/
52
53/* PRIVATE FUNCTIONS **********************************************************/
54
56{
57 /* Reset the configuration to defaults */
58 MouseCycles = 10;
59 Resolution = 4;
60 Scaling = FALSE;
62}
63
65{
66 /* Reset all flags and counters */
68}
69
71{
72 /* Reset everything */
75
76 /* Enter streaming mode and the reset the mouse ID */
78 MouseId = 0;
80}
81
83{
84 /* Clear the packet */
85 RtlZeroMemory(Packet, sizeof(*Packet));
86
87 /* Acquire the mutex */
89
90 Packet->Flags |= MOUSE_ALWAYS_SET;
91
92 /* Set the sign flags */
93 if (HorzCounter < 0)
94 {
95 Packet->Flags |= MOUSE_X_SIGN;
97 }
98
99 if (VertCounter < 0)
100 {
101 Packet->Flags |= MOUSE_Y_SIGN;
103 }
104
105 /* Check for horizontal overflows */
107 {
109 Packet->Flags |= MOUSE_X_OVERFLOW;
110 }
111
112 /* Check for vertical overflows */
114 {
116 Packet->Flags |= MOUSE_Y_OVERFLOW;
117 }
118
119 /* Set the button flags */
123
124 if (MouseId == 4)
125 {
128 }
129
130 if (MouseId >= 3)
131 {
132 /* Set the scroll counter */
133 Packet->Extra |= ((UCHAR)ScrollCounter & 0x0F);
134 }
135
136 /* Store the counters in the packet */
137 Packet->HorzCounter = LOBYTE(HorzCounter);
138 Packet->VertCounter = LOBYTE(VertCounter);
139
140 /* Reset the counters */
142
143 /* Release the mutex */
145}
146
148{
150 PS2QueuePush(MousePS2Port, Packet->HorzCounter);
151 PS2QueuePush(MousePS2Port, Packet->VertCounter);
152 if (MouseId >= 3) PS2QueuePush(MousePS2Port, Packet->Extra);
153}
154
156{
157 /* Check if we were waiting for a data byte */
159 {
161
162 switch (MouseDataByteWait)
163 {
164 /* Set Resolution */
165 case 0xE8:
166 {
168 break;
169 }
170
171 /* Set Sample Rate */
172 case 0xF3:
173 {
174 /* Check for the scroll wheel enabling sequence */
175 if (MouseId == 0)
176 {
178 {
180 if (ScrollMagicCounter == 3) MouseId = 3;
181 }
182 else
183 {
185 }
186 }
187
188 /* Check for the 5-button enabling sequence */
189 if (MouseId == 3)
190 {
192 {
194 if (ExtraButtonMagicCounter == 3) MouseId = 4;
195 }
196 else
197 {
199 }
200 }
201
202 MouseCycles = 1000 / (UINT)Command;
203 break;
204 }
205
206 default:
207 {
208 /* Shouldn't happen */
209 ASSERT(FALSE);
210 }
211 }
212
214 return;
215 }
216
217 /* Check if we're in wrap mode */
218 if (Mode == MOUSE_WRAP_MODE)
219 {
220 /*
221 * In this mode, we just echo whatever byte we get,
222 * except for the 0xEC and 0xFF commands.
223 */
224 if (Command != 0xEC && Command != 0xFF)
225 {
227 return;
228 }
229 }
230
231 switch (Command)
232 {
233 /* Set 1:1 Scaling */
234 case 0xE6:
235 {
236 Scaling = FALSE;
238 break;
239 }
240
241 /* Set 2:1 Scaling */
242 case 0xE7:
243 {
244 Scaling = TRUE;
246 break;
247 }
248
249 /* Set Resolution */
250 case 0xE8:
251 /* Set Sample Rate */
252 case 0xF3:
253 {
256 break;
257 }
258
259 /* Read Status */
260 case 0xE9:
261 {
262 BYTE Status = ButtonState & 7;
263
264 if (Scaling) Status |= 1 << 4;
265 if (MouseReporting) Status |= 1 << 5;
266 if (Mode == MOUSE_REMOTE_MODE) Status |= 1 << 6;
267
272 break;
273 }
274
275 /* Enter Streaming Mode */
276 case 0xEA:
277 {
280
282 break;
283 }
284
285 /* Read Packet */
286 case 0xEB:
287 {
291 break;
292 }
293
294 /* Return from Wrap Mode */
295 case 0xEC:
296 {
297 if (Mode == MOUSE_WRAP_MODE)
298 {
299 /* Restore the previous mode */
303 }
304 else
305 {
307 }
308
309 break;
310 }
311
312 /* Enter Wrap Mode */
313 case 0xEE:
314 {
315 if (Mode != MOUSE_WRAP_MODE)
316 {
317 /* Save the previous mode */
319 }
320
323
325 break;
326 }
327
328 /* Enter Remote Mode */
329 case 0xF0:
330 {
333
335 break;
336 }
337
338 /* Get Mouse ID */
339 case 0xF2:
340 {
343 break;
344 }
345
346 /* Enable Reporting */
347 case 0xF4:
348 {
352 break;
353 }
354
355 /* Disable Reporting */
356 case 0xF5:
357 {
361 break;
362 }
363
364 /* Set Defaults */
365 case 0xF6:
366 {
367 /* Reset the configuration and counters */
371 break;
372 }
373
374 /* Resend */
375 case 0xFE:
376 {
379 break;
380 }
381
382 /* Reset */
383 case 0xFF:
384 {
385 /* Send ACKnowledge */
387
388 MouseReset();
389
390 /* Send the Basic Assurance Test success code and the device ID */
393 break;
394 }
395
396 /* Unknown command */
397 default:
398 {
400 }
401 }
402}
403
405{
406 UNREFERENCED_PARAMETER(ElapsedTime);
407
408 /* Check if we're not in streaming mode, not reporting, or there's nothing to report */
410
413
415}
416
417/* PUBLIC FUNCTIONS ***********************************************************/
418
420{
423 *CurrentButtonState = LOBYTE(ButtonState);
425}
426
428{
429 COORD NewPosition = MouseEvent->dwMousePosition;
431
433 {
434 /* Text mode */
435 NewPosition.X *= 8;
436 NewPosition.Y *= 8;
437 }
438
439 /* Adjust for double vision */
440 if (DoubleWidth) NewPosition.X /= 2;
441 if (DoubleHeight) NewPosition.Y /= 2;
442
444
445 /* Update the counters */
446 HorzCounter += (NewPosition.X - Position.X) << DoubleWidth;
447 VertCounter += (NewPosition.Y - Position.Y) << DoubleHeight;
448
449 /* Update the position */
450 Position = NewPosition;
451
452 /* Update the button state */
453 ButtonState = MouseEvent->dwButtonState;
454
455 if (MouseEvent->dwEventFlags & MOUSE_WHEELED)
456 {
457 ScrollCounter += (SHORT)HIWORD(MouseEvent->dwButtonState);
458 }
459
462}
463
464BOOLEAN MouseInit(BYTE PS2Connector)
465{
466 /* Finish to plug the mouse to the specified PS/2 port */
467 MousePS2Port = PS2Connector;
469
471 if (MouseMutex == NULL) return FALSE;
472
474 HZ_TO_NS(100),
476
477 MouseReset();
478 return TRUE;
479}
unsigned char BOOLEAN
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
#define HZ_TO_NS(Freq)
Definition: clock.h:20
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
ButtonState
Definition: button.c:144
#define INFINITE
Definition: serial.h:102
Status
Definition: gdiplustypes.h:25
#define MOUSE_ACK
Definition: i8042prt.h:285
#define MOUSE_ERROR
Definition: i8042prt.h:286
#define LOBYTE(W)
Definition: jmemdos.c:487
#define ASSERT(a)
Definition: mode.c:44
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
unsigned int UINT
Definition: ndis.h:50
#define FASTCALL
Definition: nt_native.h:50
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
ULONG CurrentPosition
Definition: patchapi.h:57
BYTE * PBYTE
Definition: pedump.c:66
short SHORT
Definition: pedump.c:59
VOID PS2SetDeviceCmdProc(BYTE PS2Port, LPVOID Param, PS2_DEVICE_CMDPROC DeviceCommand)
Definition: ps2.c:478
BOOLEAN PS2QueuePush(BYTE PS2Port, BYTE Data)
Definition: ps2.c:486
Definition: shell.h:41
Definition: bl.h:1338
ULONG Y
Definition: bl.h:1340
ULONG X
Definition: bl.h:1339
DWORD dwEventFlags
Definition: wincon.h:257
DWORD dwButtonState
Definition: wincon.h:255
COORD dwMousePosition
Definition: wincon.h:254
PHARDWARE_TIMER CreateHardwareTimer(ULONG Flags, ULONGLONG Delay, PHARDWARE_TIMER_PROC Callback)
Definition: clock.c:144
BOOLEAN VgaGetDoubleVisionState(PBOOLEAN Horizontal, PBOOLEAN Vertical)
Definition: video.c:488
static BOOLEAN DoubleHeight
Definition: video.c:59
static BOOLEAN DoubleWidth
Definition: video.c:58
static VOID MouseDispatchPacket(PMOUSE_PACKET Packet)
Definition: mouse.c:147
static const BYTE ExtraButtonMagic[3]
Definition: mouse.c:28
static BYTE ScrollMagicCounter
Definition: mouse.c:45
static ULONG ButtonState
Definition: mouse.c:39
static BYTE Resolution
Definition: mouse.c:35
static BOOLEAN EventsOccurred
Definition: mouse.c:43
static UINT MouseCycles
Definition: mouse.c:47
static VOID MouseResetCounters(VOID)
Definition: mouse.c:64
VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent)
Definition: mouse.c:427
VOID MouseGetDataFast(PCOORD CurrentPosition, PBYTE CurrentButtonState)
Definition: mouse.c:419
static VOID FASTCALL MouseStreamingCallback(ULONGLONG ElapsedTime)
Definition: mouse.c:404
static MOUSE_PACKET LastPacket
Definition: mouse.c:32
static VOID MouseResetConfig(VOID)
Definition: mouse.c:55
BOOLEAN MouseInit(BYTE PS2Connector)
Definition: mouse.c:464
static CHAR ScrollCounter
Definition: mouse.c:42
static BYTE MouseDataByteWait
Definition: mouse.c:44
static SHORT VertCounter
Definition: mouse.c:41
static HANDLE MouseMutex
Definition: mouse.c:30
static BOOLEAN Scaling
Definition: mouse.c:36
static BYTE MousePS2Port
Definition: mouse.c:49
static VOID MouseGetPacket(PMOUSE_PACKET Packet)
Definition: mouse.c:82
static BYTE MouseId
Definition: mouse.c:38
static COORD Position
Definition: mouse.c:34
static BOOLEAN MouseReporting
Definition: mouse.c:37
static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
Definition: mouse.c:155
static PHARDWARE_TIMER StreamTimer
Definition: mouse.c:31
static MOUSE_MODE Mode
Definition: mouse.c:33
static MOUSE_MODE PreviousMode
Definition: mouse.c:33
static SHORT HorzCounter
Definition: mouse.c:40
static const BYTE ScrollMagic[3]
Definition: mouse.c:27
static BYTE ExtraButtonMagicCounter
Definition: mouse.c:45
static VOID MouseReset(VOID)
Definition: mouse.c:70
#define MOUSE_BAT_SUCCESS
Definition: mouse.h:32
#define MOUSE_Y_OVERFLOW
Definition: mouse.h:25
#define MOUSE_5TH_BUTTON
Definition: mouse.h:29
#define MOUSE_X_OVERFLOW
Definition: mouse.h:24
#define MOUSE_ALWAYS_SET
Definition: mouse.h:21
#define MOUSE_RIGHT_BUTTON
Definition: mouse.h:19
@ MOUSE_REMOTE_MODE
Definition: mouse.h:51
@ MOUSE_WRAP_MODE
Definition: mouse.h:52
@ MOUSE_STREAMING_MODE
Definition: mouse.h:50
#define MOUSE_X_SIGN
Definition: mouse.h:22
#define MOUSE_MAX
Definition: mouse.h:15
#define MOUSE_Y_SIGN
Definition: mouse.h:23
#define MOUSE_4TH_BUTTON
Definition: mouse.h:28
enum _MOUSE_MODE MOUSE_MODE
#define MOUSE_MIDDLE_BUTTON
Definition: mouse.h:20
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:18
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseMutex(IN HANDLE hMutex)
Definition: synch.c:618
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define HIWORD(l)
Definition: typedefs.h:247
#define CreateMutex
Definition: winbase.h:3691
#define FROM_LEFT_4TH_BUTTON_PRESSED
Definition: wincon.h:163
#define FROM_LEFT_2ND_BUTTON_PRESSED
Definition: wincon.h:161
#define FROM_LEFT_3RD_BUTTON_PRESSED
Definition: wincon.h:162
#define FROM_LEFT_1ST_BUTTON_PRESSED
Definition: wincon.h:159
#define RIGHTMOST_BUTTON_PRESSED
Definition: wincon.h:160
#define MOUSE_WHEELED
Definition: wincon.h:170
#define WINAPI
Definition: msvc.h:6
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193