mirror of
https://github.com/reactos/reactos.git
synced 2024-07-31 00:28:56 +00:00
[NTVDM]
Start implementing mouse support. svn path=/trunk/; revision=63842
This commit is contained in:
parent
8a230af1a7
commit
9065679ba7
|
@ -19,6 +19,7 @@ list(APPEND SOURCE
|
||||||
hardware/speaker.c
|
hardware/speaker.c
|
||||||
hardware/timer.c
|
hardware/timer.c
|
||||||
hardware/vga.c
|
hardware/vga.c
|
||||||
|
hardware/mouse.c
|
||||||
dos/dos32krnl/bios.c
|
dos/dos32krnl/bios.c
|
||||||
dos/dos32krnl/dos.c
|
dos/dos32krnl/dos.c
|
||||||
dos/dos32krnl/dosfiles.c
|
dos/dos32krnl/dosfiles.c
|
||||||
|
|
329
reactos/subsystems/ntvdm/hardware/mouse.c
Normal file
329
reactos/subsystems/ntvdm/hardware/mouse.c
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Virtual DOS Machine
|
||||||
|
* FILE: mouse.c
|
||||||
|
* PURPOSE: Mouse emulation
|
||||||
|
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
|
||||||
|
#include "mouse.h"
|
||||||
|
#include "ps2.h"
|
||||||
|
|
||||||
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
|
static MOUSE_MODE Mode, PreviousMode;
|
||||||
|
static COORD Position;
|
||||||
|
static ULONG WidthMm, HeightMm, WidthPixels, HeightPixels;
|
||||||
|
static ULONG SampleRate;
|
||||||
|
static ULONG Resolution;
|
||||||
|
static BOOLEAN Scaling;
|
||||||
|
static BOOLEAN Reporting;
|
||||||
|
static BYTE MouseId;
|
||||||
|
static ULONG ButtonState;
|
||||||
|
static SHORT HorzCounter;
|
||||||
|
static SHORT VertCounter;
|
||||||
|
static CHAR ScrollCounter;
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
static VOID MouseResetConfig(VOID)
|
||||||
|
{
|
||||||
|
/* Reset the configuration to defaults */
|
||||||
|
SampleRate = 100;
|
||||||
|
Resolution = 4;
|
||||||
|
Scaling = FALSE;
|
||||||
|
Reporting = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID MouseResetCounters(VOID)
|
||||||
|
{
|
||||||
|
/* Reset all flags and counters */
|
||||||
|
ButtonState = HorzCounter = VertCounter = ScrollCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID MouseReset(VOID)
|
||||||
|
{
|
||||||
|
/* Reset everything */
|
||||||
|
MouseResetConfig();
|
||||||
|
MouseResetCounters();
|
||||||
|
|
||||||
|
/* Enter streaming mode and the reset the mouse ID */
|
||||||
|
Mode = MOUSE_STREAMING_MODE;
|
||||||
|
MouseId = 0;
|
||||||
|
|
||||||
|
/* Send the Basic Assurance Test success code and the device ID */
|
||||||
|
KeyboardQueuePush(MOUSE_BAT_SUCCESS);
|
||||||
|
KeyboardQueuePush(MouseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static VOID MouseGetPacket(PMOUSE_PACKET Packet)
|
||||||
|
{
|
||||||
|
/* Clear the packet */
|
||||||
|
ZeroMemory(Packet, sizeof(MOUSE_PACKET));
|
||||||
|
|
||||||
|
Packet->Flags |= MOUSE_ALWAYS_SET;
|
||||||
|
|
||||||
|
/* Check for horizontal overflows */
|
||||||
|
if ((HorzCounter < MOUSE_MIN) || (HorzCounter > MOUSE_MAX))
|
||||||
|
{
|
||||||
|
if (HorzCounter > MOUSE_MAX) HorzCounter = MOUSE_MAX;
|
||||||
|
if (HorzCounter < MOUSE_MIN) HorzCounter = MOUSE_MIN;
|
||||||
|
|
||||||
|
Packet->Flags |= MOUSE_X_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for vertical overflows */
|
||||||
|
if ((VertCounter < MOUSE_MIN) || (VertCounter > MOUSE_MAX))
|
||||||
|
{
|
||||||
|
if (VertCounter > MOUSE_MIN) VertCounter = MOUSE_MIN;
|
||||||
|
if (VertCounter < MOUSE_MIN) VertCounter = MOUSE_MIN;
|
||||||
|
|
||||||
|
Packet->Flags |= MOUSE_Y_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the sign flags */
|
||||||
|
if (HorzCounter & MOUSE_SIGN_BIT) Packet->Flags |= MOUSE_X_SIGN;
|
||||||
|
if (HorzCounter & MOUSE_SIGN_BIT) Packet->Flags |= MOUSE_Y_SIGN;
|
||||||
|
|
||||||
|
/* Set the button flags */
|
||||||
|
if (ButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) Packet->Flags |= MOUSE_LEFT_BUTTON;
|
||||||
|
if (ButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) Packet->Flags |= MOUSE_MIDDLE_BUTTON;
|
||||||
|
if (ButtonState & RIGHTMOST_BUTTON_PRESSED) Packet->Flags |= MOUSE_RIGHT_BUTTON;
|
||||||
|
|
||||||
|
if (MouseId == 4)
|
||||||
|
{
|
||||||
|
if (ButtonState & FROM_LEFT_3RD_BUTTON_PRESSED) Packet->Extra |= MOUSE_4TH_BUTTON;
|
||||||
|
if (ButtonState & FROM_LEFT_4TH_BUTTON_PRESSED) Packet->Extra |= MOUSE_5TH_BUTTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MouseId >= 3)
|
||||||
|
{
|
||||||
|
/* Set the scroll counter */
|
||||||
|
Packet->Extra |= (UCHAR)ScrollCounter & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the counters in the packet */
|
||||||
|
Packet->HorzCounter = LOBYTE(HorzCounter);
|
||||||
|
Packet->VertCounter = LOBYTE(VertCounter);
|
||||||
|
|
||||||
|
/* Reset the counters */
|
||||||
|
MouseResetCounters();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
VOID MouseUpdatePosition(PCOORD NewPosition)
|
||||||
|
{
|
||||||
|
/* Update the counters */
|
||||||
|
HorzCounter += ((NewPosition->X - Position.X) * WidthMm * Resolution) / WidthPixels;
|
||||||
|
VertCounter += ((NewPosition->Y - Position.Y) * HeightMm * Resolution) / HeightPixels;
|
||||||
|
|
||||||
|
/* Update the position */
|
||||||
|
Position = *NewPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID MouseUpdateButtons(ULONG NewButtonState)
|
||||||
|
{
|
||||||
|
ButtonState = NewButtonState;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID MouseScroll(LONG Direction)
|
||||||
|
{
|
||||||
|
ScrollCounter += Direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
COORD MouseGetPosition(VOID)
|
||||||
|
{
|
||||||
|
return Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID MouseCommand(BYTE Command)
|
||||||
|
{
|
||||||
|
switch (Command)
|
||||||
|
{
|
||||||
|
/* Set 1:1 Scaling */
|
||||||
|
case 0xE6:
|
||||||
|
{
|
||||||
|
Scaling = FALSE;
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set 2:1 Scaling */
|
||||||
|
case 0xE7:
|
||||||
|
{
|
||||||
|
Scaling = TRUE;
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Resolution */
|
||||||
|
case 0xE8:
|
||||||
|
{
|
||||||
|
// TODO: NOT IMPLEMENTED
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read Status */
|
||||||
|
case 0xE9:
|
||||||
|
{
|
||||||
|
// TODO: NOT IMPLEMENTED
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter Streaming Mode */
|
||||||
|
case 0xEA:
|
||||||
|
{
|
||||||
|
MouseResetCounters();
|
||||||
|
Mode = MOUSE_STREAMING_MODE;
|
||||||
|
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read Packet */
|
||||||
|
case 0xEB:
|
||||||
|
{
|
||||||
|
// TODO: NOT IMPLEMENTED
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return From Wrap Mode */
|
||||||
|
case 0xEC:
|
||||||
|
{
|
||||||
|
if (Mode == MOUSE_WRAP_MODE)
|
||||||
|
{
|
||||||
|
/* Restore the previous mode */
|
||||||
|
MouseResetCounters();
|
||||||
|
Mode = PreviousMode;
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
}
|
||||||
|
else KeyboardQueuePush(MOUSE_ERROR);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter Wrap Mode */
|
||||||
|
case 0xEE:
|
||||||
|
{
|
||||||
|
if (Mode != MOUSE_WRAP_MODE)
|
||||||
|
{
|
||||||
|
/* Save the previous mode */
|
||||||
|
PreviousMode = Mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseResetCounters();
|
||||||
|
Mode = MOUSE_WRAP_MODE;
|
||||||
|
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter Remote Mode */
|
||||||
|
case 0xF0:
|
||||||
|
{
|
||||||
|
MouseResetCounters();
|
||||||
|
Mode = MOUSE_REMOTE_MODE;
|
||||||
|
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Mouse ID */
|
||||||
|
case 0xF2:
|
||||||
|
{
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
KeyboardQueuePush(MouseId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Sample Rate */
|
||||||
|
case 0xF3:
|
||||||
|
{
|
||||||
|
// TODO: NOT IMPLEMENTED
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable Reporting */
|
||||||
|
case 0xF4:
|
||||||
|
{
|
||||||
|
Reporting = TRUE;
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable Reporting */
|
||||||
|
case 0xF5:
|
||||||
|
{
|
||||||
|
Reporting = FALSE;
|
||||||
|
KeyboardQueuePush(MOUSE_ACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Defaults */
|
||||||
|
case 0xF6:
|
||||||
|
{
|
||||||
|
/* Reset the configuration and counters */
|
||||||
|
MouseResetConfig();
|
||||||
|
MouseResetCounters();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resend */
|
||||||
|
case 0xFE:
|
||||||
|
{
|
||||||
|
// TODO: NOT IMPLEMENTED
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
case 0xFF:
|
||||||
|
{
|
||||||
|
MouseReset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unknown command */
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
KeyboardQueuePush(MOUSE_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN MouseInit(VOID)
|
||||||
|
{
|
||||||
|
HWND hWnd;
|
||||||
|
HDC hDC;
|
||||||
|
|
||||||
|
/* Get the console window */
|
||||||
|
hWnd = GetConsoleWindow();
|
||||||
|
if (hWnd == NULL) return FALSE;
|
||||||
|
|
||||||
|
/* Get the console window's device context */
|
||||||
|
hDC = GetWindowDC(hWnd);
|
||||||
|
if (hDC == NULL) return FALSE;
|
||||||
|
|
||||||
|
/* Get the parameters */
|
||||||
|
WidthMm = (ULONG)GetDeviceCaps(hDC, HORZSIZE);
|
||||||
|
HeightMm = (ULONG)GetDeviceCaps(hDC, VERTSIZE);
|
||||||
|
WidthPixels = (ULONG)GetDeviceCaps(hDC, HORZRES);
|
||||||
|
HeightPixels = (ULONG)GetDeviceCaps(hDC, VERTRES);
|
||||||
|
|
||||||
|
/* Release the device context */
|
||||||
|
ReleaseDC(hWnd, hDC);
|
||||||
|
|
||||||
|
MouseReset();
|
||||||
|
return TRUE;
|
||||||
|
}
|
78
reactos/subsystems/ntvdm/hardware/mouse.h
Normal file
78
reactos/subsystems/ntvdm/hardware/mouse.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Virtual DOS Machine
|
||||||
|
* FILE: mouse.h
|
||||||
|
* PURPOSE: Mouse emulation
|
||||||
|
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MOUSE_H_
|
||||||
|
#define _MOUSE_H_
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#include "ntvdm.h"
|
||||||
|
|
||||||
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
|
/* Mouse packet constants */
|
||||||
|
#define MOUSE_MIN -256
|
||||||
|
#define MOUSE_MAX 255
|
||||||
|
#define MOUSE_SIGN_BIT (1 << 8)
|
||||||
|
|
||||||
|
/* Mouse packet flags */
|
||||||
|
#define MOUSE_LEFT_BUTTON (1 << 0)
|
||||||
|
#define MOUSE_RIGHT_BUTTON (1 << 1)
|
||||||
|
#define MOUSE_MIDDLE_BUTTON (1 << 2)
|
||||||
|
#define MOUSE_ALWAYS_SET (1 << 3)
|
||||||
|
#define MOUSE_X_SIGN (1 << 4)
|
||||||
|
#define MOUSE_Y_SIGN (1 << 5)
|
||||||
|
#define MOUSE_X_OVERFLOW (1 << 6)
|
||||||
|
#define MOUSE_Y_OVERFLOW (1 << 7)
|
||||||
|
|
||||||
|
/* Mouse packet extra flags */
|
||||||
|
#define MOUSE_4TH_BUTTON (1 << 4)
|
||||||
|
#define MOUSE_5TH_BUTTON (1 << 5)
|
||||||
|
|
||||||
|
/* Command responses */
|
||||||
|
#define MOUSE_BAT_SUCCESS 0xAA
|
||||||
|
#define MOUSE_ACK 0xFA
|
||||||
|
#define MOUSE_ERROR 0xFC
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scrolling directions
|
||||||
|
*
|
||||||
|
* It may seem odd that the directions are implemented this way, but
|
||||||
|
* this is how it's done on real hardware. It works because the two
|
||||||
|
* scroll wheels can't be used at the same time.
|
||||||
|
*/
|
||||||
|
#define MOUSE_SCROLL_UP 1
|
||||||
|
#define MOUSE_SCROLL_DOWN -1
|
||||||
|
#define MOUSE_SCROLL_RIGHT 2
|
||||||
|
#define MOUSE_SCROLL_LET -2
|
||||||
|
|
||||||
|
typedef enum _MOUSE_MODE
|
||||||
|
{
|
||||||
|
MOUSE_STREAMING_MODE,
|
||||||
|
MOUSE_REMOTE_MODE,
|
||||||
|
MOUSE_WRAP_MODE,
|
||||||
|
} MOUSE_MODE, *PMOUSE_MODE;
|
||||||
|
|
||||||
|
typedef struct _MOUSE_PACKET
|
||||||
|
{
|
||||||
|
BYTE Flags;
|
||||||
|
BYTE HorzCounter;
|
||||||
|
BYTE VertCounter;
|
||||||
|
BYTE Extra;
|
||||||
|
} MOUSE_PACKET, *PMOUSE_PACKET;
|
||||||
|
|
||||||
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
VOID MouseUpdatePosition(PCOORD NewPosition);
|
||||||
|
VOID MouseUpdateButtons(ULONG NewButtonState);
|
||||||
|
VOID MouseScroll(LONG Direction);
|
||||||
|
COORD MouseGetPosition(VOID);
|
||||||
|
VOID MouseCommand(BYTE Command);
|
||||||
|
BOOLEAN MouseInit(VOID);
|
||||||
|
|
||||||
|
#endif // _MOUSE_H_
|
|
@ -14,6 +14,7 @@
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "ps2.h"
|
#include "ps2.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
|
#include "mouse.h"
|
||||||
|
|
||||||
/* PRIVATE VARIABLES **********************************************************/
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
|
@ -28,69 +29,6 @@ static HANDLE QueueMutex = NULL;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
|
|
||||||
{
|
|
||||||
BOOLEAN Result = TRUE;
|
|
||||||
|
|
||||||
WaitForSingleObject(QueueMutex, INFINITE);
|
|
||||||
|
|
||||||
/* Check if the keyboard queue is full */
|
|
||||||
if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
|
|
||||||
{
|
|
||||||
Result = FALSE;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert the value in the queue */
|
|
||||||
KeyboardQueue[KeyboardQueueEnd] = ScanCode;
|
|
||||||
KeyboardQueueEnd++;
|
|
||||||
KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE;
|
|
||||||
|
|
||||||
/* Since we inserted a value, it's not empty anymore */
|
|
||||||
KeyboardQueueEmpty = FALSE;
|
|
||||||
|
|
||||||
Done:
|
|
||||||
ReleaseMutex(QueueMutex);
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
|
|
||||||
{
|
|
||||||
BOOLEAN Result = TRUE;
|
|
||||||
|
|
||||||
/* Make sure the keyboard queue is not empty (fast check) */
|
|
||||||
if (KeyboardQueueEmpty) return FALSE;
|
|
||||||
|
|
||||||
WaitForSingleObject(QueueMutex, INFINITE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Recheck whether keyboard queue is not empty (it
|
|
||||||
* may have changed after having grabbed the mutex).
|
|
||||||
*/
|
|
||||||
if (KeyboardQueueEmpty)
|
|
||||||
{
|
|
||||||
Result = FALSE;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the scan code */
|
|
||||||
*ScanCode = KeyboardQueue[KeyboardQueueStart];
|
|
||||||
|
|
||||||
/* Remove the value from the queue */
|
|
||||||
KeyboardQueueStart++;
|
|
||||||
KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE;
|
|
||||||
|
|
||||||
/* Check if the queue is now empty */
|
|
||||||
if (KeyboardQueueStart == KeyboardQueueEnd)
|
|
||||||
{
|
|
||||||
KeyboardQueueEmpty = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Done:
|
|
||||||
ReleaseMutex(QueueMutex);
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BYTE WINAPI PS2ReadPort(ULONG Port)
|
static BYTE WINAPI PS2ReadPort(ULONG Port)
|
||||||
{
|
{
|
||||||
if (Port == PS2_CONTROL_PORT)
|
if (Port == PS2_CONTROL_PORT)
|
||||||
|
@ -156,14 +94,14 @@ static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
|
||||||
/* Disable mouse */
|
/* Disable mouse */
|
||||||
case 0xA7:
|
case 0xA7:
|
||||||
{
|
{
|
||||||
// TODO: Mouse support
|
// TODO: Not implemented
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable mouse */
|
/* Enable mouse */
|
||||||
case 0xA8:
|
case 0xA8:
|
||||||
{
|
{
|
||||||
// TODO: Mouse support
|
// TODO: Not implemented
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +206,7 @@ static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
|
||||||
|
|
||||||
case 0xD4:
|
case 0xD4:
|
||||||
{
|
{
|
||||||
// TODO: Mouse support
|
MouseCommand(Data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,6 +220,69 @@ static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
BOOLEAN KeyboardQueuePush(BYTE ScanCode)
|
||||||
|
{
|
||||||
|
BOOLEAN Result = TRUE;
|
||||||
|
|
||||||
|
WaitForSingleObject(QueueMutex, INFINITE);
|
||||||
|
|
||||||
|
/* Check if the keyboard queue is full */
|
||||||
|
if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
|
||||||
|
{
|
||||||
|
Result = FALSE;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the value in the queue */
|
||||||
|
KeyboardQueue[KeyboardQueueEnd] = ScanCode;
|
||||||
|
KeyboardQueueEnd++;
|
||||||
|
KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE;
|
||||||
|
|
||||||
|
/* Since we inserted a value, it's not empty anymore */
|
||||||
|
KeyboardQueueEmpty = FALSE;
|
||||||
|
|
||||||
|
Done:
|
||||||
|
ReleaseMutex(QueueMutex);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
|
||||||
|
{
|
||||||
|
BOOLEAN Result = TRUE;
|
||||||
|
|
||||||
|
/* Make sure the keyboard queue is not empty (fast check) */
|
||||||
|
if (KeyboardQueueEmpty) return FALSE;
|
||||||
|
|
||||||
|
WaitForSingleObject(QueueMutex, INFINITE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recheck whether keyboard queue is not empty (it
|
||||||
|
* may have changed after having grabbed the mutex).
|
||||||
|
*/
|
||||||
|
if (KeyboardQueueEmpty)
|
||||||
|
{
|
||||||
|
Result = FALSE;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the scan code */
|
||||||
|
*ScanCode = KeyboardQueue[KeyboardQueueStart];
|
||||||
|
|
||||||
|
/* Remove the value from the queue */
|
||||||
|
KeyboardQueueStart++;
|
||||||
|
KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE;
|
||||||
|
|
||||||
|
/* Check if the queue is now empty */
|
||||||
|
if (KeyboardQueueStart == KeyboardQueueEnd)
|
||||||
|
{
|
||||||
|
KeyboardQueueEmpty = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
ReleaseMutex(QueueMutex);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
VOID PS2Dispatch(PINPUT_RECORD InputRecord)
|
VOID PS2Dispatch(PINPUT_RECORD InputRecord)
|
||||||
{
|
{
|
||||||
/* Check the event type */
|
/* Check the event type */
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN KeyboardQueuePush(BYTE ScanCode);
|
||||||
|
BOOLEAN KeyboardQueuePop(BYTE *ScanCode);
|
||||||
VOID PS2Dispatch(PINPUT_RECORD InputRecord);
|
VOID PS2Dispatch(PINPUT_RECORD InputRecord);
|
||||||
VOID GenerateKeyboardInterrupts(VOID);
|
VOID GenerateKeyboardInterrupts(VOID);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue