808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* $Id$ */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/** @file
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * VBox NT4 Mouse Driver
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/*
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Copyright (C) 2011-2012 Oracle Corporation
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * available from http://www.virtualbox.org. This file is free software;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * you can redistribute it and/or modify it under the terms of the GNU
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * General Public License (GPL) as published by the Free Software
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define LOG_GROUP LOG_GROUP_DRV_MOUSE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <iprt/asm.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <VBox/err.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <VBox/log.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <VBox/VBoxGuestLib.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <stdarg.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <string.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncRT_C_DECLS_BEGIN
7519a1c4323fa86fbb19a36a91cd25abfd7af714vboxsync#define _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#undef PAGE_SIZE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#undef PAGE_SHIFT
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <ntddk.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <ntddkbd.h>
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#include <ntddmou.h>
7519a1c4323fa86fbb19a36a91cd25abfd7af714vboxsync#undef _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncRT_C_DECLS_END
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* not available on NT4 */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#undef ExFreePool
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#undef ExAllocatePool
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* i8042 mouse status bits */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define LEFT_BUTTON_DOWN 0x01
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define RIGHT_BUTTON_DOWN 0x02
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MIDDLE_BUTTON_DOWN 0x04
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define X_DATA_SIGN 0x10
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define Y_DATA_SIGN 0x20
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define X_OVERFLOW 0x40
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define Y_OVERFLOW 0x80
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_SIGN_OVERFLOW_MASK (X_DATA_SIGN | Y_DATA_SIGN | X_OVERFLOW | Y_OVERFLOW)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_MAXIMUM_POSITIVE_DELTA 0x000000FF
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_MAXIMUM_NEGATIVE_DELTA 0xFFFFFF00
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define KEYBOARD_HARDWARE_PRESENT 0x01
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_HARDWARE_PRESENT 0x02
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define BALLPOINT_HARDWARE_PRESENT 0x04
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define WHEELMOUSE_HARDWARE_PRESENT 0x08
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8X_PUT_COMMAND_BYTE(Address, Byte) WRITE_PORT_UCHAR(Address, (UCHAR) Byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8X_PUT_DATA_BYTE(Address, Byte) WRITE_PORT_UCHAR(Address, (UCHAR) Byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8X_GET_STATUS_BYTE(Address) READ_PORT_UCHAR(Address)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8X_GET_DATA_BYTE(Address) READ_PORT_UCHAR(Address)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* commands to the i8042 controller */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_READ_CONTROLLER_COMMAND_BYTE 0x20
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_WRITE_CONTROLLER_COMMAND_BYTE 0x60
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_DISABLE_MOUSE_DEVICE 0xA7
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_ENABLE_MOUSE_DEVICE 0xA8
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_AUXILIARY_DEVICE_TEST 0xA9
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_KEYBOARD_DEVICE_TEST 0xAB
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_DISABLE_KEYBOARD_DEVICE 0xAD
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_ENABLE_KEYBOARD_DEVICE 0xAE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define I8042_WRITE_TO_AUXILIARY_DEVICE 0xD4
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* i8042 Controller Command Byte */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define CCB_ENABLE_KEYBOARD_INTERRUPT 0x01
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define CCB_ENABLE_MOUSE_INTERRUPT 0x02
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define CCB_DISABLE_KEYBOARD_DEVICE 0x10
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define CCB_DISABLE_MOUSE_DEVICE 0x20
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define CCB_KEYBOARD_TRANSLATE_MODE 0x40
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* i8042 Controller Status Register bits */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define OUTPUT_BUFFER_FULL 0x01
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define INPUT_BUFFER_FULL 0x02
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_OUTPUT_BUFFER_FULL 0x20
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* i8042 responses */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define ACKNOWLEDGE 0xFA
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define RESEND 0xFE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* commands to the keyboard (through the 8042 data port) */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SET_KEYBOARD_INDICATORS 0xED
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SELECT_SCAN_CODE_SET 0xF0
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define READ_KEYBOARD_ID 0xF2
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SET_KEYBOARD_TYPEMATIC 0xF3
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SET_ALL_TYPEMATIC_MAKE_BREAK 0xFA
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define KEYBOARD_RESET 0xFF
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* commands to the mouse (through the 8042 data port) */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SET_MOUSE_SCALING_1TO1 0xE6
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SET_MOUSE_RESOLUTION 0xE8
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define READ_MOUSE_STATUS 0xE9
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define GET_DEVICE_ID 0xF2
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define SET_MOUSE_SAMPLING_RATE 0xF3
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define ENABLE_MOUSE_TRANSMISSION 0xF4
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_RESET 0xFF
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* mouse responses */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_COMPLETE 0xAA
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define MOUSE_ID_BYTE 0x00
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define WHEELMOUSE_ID_BYTE 0x03
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* maximum number of pointer/keyboard port names the port driver */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define POINTER_PORTS_MAXIMUM 8
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define KEYBOARD_PORTS_MAXIMUM 8
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* NtDeviceIoControlFile internal IoControlCode values for keyboard device */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_KEYBOARD_CONNECT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0080, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_KEYBOARD_DISCONNECT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0100, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_KEYBOARD_ENABLE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0200, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_KEYBOARD_DISABLE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0400, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* NtDeviceIoControlFile internal IoControlCode values for mouse device */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_MOUSE_CONNECT CTL_CODE(FILE_DEVICE_MOUSE, 0x0080, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_MOUSE_DISCONNECT CTL_CODE(FILE_DEVICE_MOUSE, 0x0100, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_MOUSE_ENABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0200, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define IOCTL_INTERNAL_MOUSE_DISABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0400, METHOD_NEITHER, FILE_ANY_ACCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* i8042 controller input/output ports */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef enum _I8042IOPORTTYPE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync i8042Dat = 0,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync i8042Cmd,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync i8042MaxPorts
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} I8042IOPORTTYPE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* device types attached to the i8042 controller */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef enum _I8042DEVTYPE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CtrlDevType,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdDevType,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouDevType,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NoDevice
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} I8042DEVTYPE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* keyboard output states */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef enum _KBDSTATE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Idle,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SendFirstByte,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SendLastByte
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} KBDSTATE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* keyboard scan code input states */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef enum _KBDSCANSTATE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Normal,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GotE0,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GotE1
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} KBDSCANSTATE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* mouse states */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef enum _MOUSTATE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouseIdle,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync XMovement,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync YMovement,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ZMovement,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouseExpectingACK
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} MOUSTATE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef VOID (*PSERVICECALLBACK)(PVOID Ctx, PVOID pArg1, PVOID pArg2, PVOID pArg3);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _CONNECT_DATA
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT ClassDeviceObject;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PSERVICECALLBACK ClassService;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} CONNECT_DATA, *PCONNECT_DATA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _KBDSETPACKET
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT State;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR FirstByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR LastByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} KBDSETPACKET, *PKBDSETPACKET;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _I8042CFGINF
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE InterfaceType; /**< bus interface type */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG uBusNr; /**< bus number */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cPorts;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CM_PARTIAL_RESOURCE_DESCRIPTOR aPorts[i8042MaxPorts];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CM_PARTIAL_RESOURCE_DESCRIPTOR KbdInt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CM_PARTIAL_RESOURCE_DESCRIPTOR MouInt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fFloatSave; /**< weather to save floating point context */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT iResend; /**< number of retries allowed */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT PollingIterations; /**< number of polling iterations */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT PollingIterationsMaximum;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT PollStatusIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT StallMicroseconds;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KEYBOARD_ATTRIBUTES KbdAttr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KEYBOARD_TYPEMATIC_PARAMETERS KeyRepeatCurrent;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KEYBOARD_INDICATOR_PARAMETERS KbdInd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MOUSE_ATTRIBUTES MouAttr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT MouseResolution;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG EnableWheelDetection;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} I8042CFGINF, *PI8042CFGINF;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _PORTKBDEXT
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONNECT_DATA ConnectData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_INPUT_DATA InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_INPUT_DATA DataIn;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_INPUT_DATA DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_INPUT_DATA DataEnd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KEYBOARD_INPUT_DATA CurrentInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KBDSCANSTATE CurrentScanState;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KBDSETPACKET CurrentOutput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT ResendCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KTIMER DataConsumptionTimer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT UnitId;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} PORTKBDEXT, *PPORTKBDEXT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _PORTMOUEXT
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONNECT_DATA ConnectData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PMOUSE_INPUT_DATA InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PMOUSE_INPUT_DATA DataIn;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PMOUSE_INPUT_DATA DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PMOUSE_INPUT_DATA DataEnd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MOUSE_INPUT_DATA CurrentInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT InputState;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR uCurrSignAndOverflow;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR uPrevSignAndOverflow;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR PreviousButtons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KTIMER DataConsumptionTimer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER PreviousTick;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT UnitId;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG SynchTickCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR LastByteReceived;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} PORTMOUEXT, *PPORTMOUEXT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _DEVEXT
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG HardwarePresent;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync volatile uint32_t KeyboardEnableCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync volatile uint32_t MouseEnableCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUCHAR DevRegs[i8042MaxPorts];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PORTKBDEXT KbdExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PORTMOUEXT MouExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8042CFGINF Cfg;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKINTERRUPT KbdIntObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKINTERRUPT MouIntObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KSPIN_LOCK ShIntObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KDPC RetriesExceededDpc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KDPC KeyboardIsrDpc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KDPC KeyboardIsrDpcRetry;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG DpcInterlockKeyboard;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KDPC MouseIsrDpc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KDPC MouseIsrDpcRetry;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG DpcInterlockMouse;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KDPC TimeOutDpc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KTIMER CommandTimer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG TimerCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fUnmapRegs;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VMMDevReqMouseStatus *pReq;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} DEVEXT, *PDEVEXT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _INITEXT
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DEVEXT DevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} INITEXT, *PINITEXT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _I8042INITDATACTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync int DevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} I8042INITDATACTX, *PI8042INITDATACTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _I8042TRANSMITCCBCTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG HwDisEnMask;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fAndOp;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR ByteMask;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS Status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} I8042TRANSMITCCBCTX, *PI8042TRANSMITCCBCTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _GETDATAPTRCTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync int DevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVOID DataIn;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVOID DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} GETDATAPTRCTX, *PGETDATAPTRCTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _SETDATAPTRCTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync int DevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVOID DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} SETDATAPTRCTX, *PSETDATAPTRCTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _TIMERCTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PLONG TimerCounter;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG NewTimerCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} TIMERCTX, *PTIMERCTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _KBDINITIATECTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR FirstByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR LastByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} KBDINITIATECTX, *PKBDINITIATECTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef enum _OPTYPE
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IncrementOperation,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DecrementOperation,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync WriteOperation,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} OPTYPE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _VAROPCTX
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PLONG VariableAddress;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync OPTYPE Operation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PLONG NewValue;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} VAROPCTX, *PVAROPCTX;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsynctypedef struct _KBDTYPEINFO
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT cFunctionKeys;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT cIndicators;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT cKeysTotal;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync} KBDTYPEINFO;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic const INDICATOR_LIST s_aIndicators[3] =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {0x3A, KEYBOARD_CAPS_LOCK_ON},
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {0x45, KEYBOARD_NUM_LOCK_ON},
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {0x46, KEYBOARD_SCROLL_LOCK_ON}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync};
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic const KBDTYPEINFO s_aKeybType[4] =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {10, 3, 84}, /* PC/XT 83- 84-key keyboard (and compatibles) */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {12, 3, 102}, /* Olivetti M24 102-key keyboard (and compatibles) */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {10, 3, 84}, /* All AT type keyboards (84-86 keys) */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {12, 3, 101} /* Enhanced 101- or 102-key keyboards (and compatibles) */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync};
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncRT_C_DECLS_BEGIN
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouFindWheel(PDEVICE_OBJECT pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID MouGetRegstry(PINITEXT pInit, PUNICODE_STRING RegistryPath,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUNICODE_STRING KeyboardDeviceName, PUNICODE_STRING PointerDeviceName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouInitHw(PDEVICE_OBJECT pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID KbdGetRegstry(PINITEXT pInit, PUNICODE_STRING RegistryPath,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUNICODE_STRING KeyboardDeviceName, PUNICODE_STRING PointerDeviceName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS KbdInitHw(PDEVICE_OBJECT pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID HwGetRegstry(PINITEXT pInit, PUNICODE_STRING RegistryPath,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUNICODE_STRING KeyboardDeviceName, PUNICODE_STRING PointerDeviceName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CreateResList(PDEVEXT pDevExt, PCM_RESOURCE_LIST *pResList, PULONG pResListSize);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID InitHw(PDEVICE_OBJECT pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouCallOut(PVOID pCtx, PUNICODE_STRING PathName,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE BusType, ULONG uBusNr, PKEY_VALUE_FULL_INFORMATION *pBusInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uCtrlType, ULONG uCtrlNr, PKEY_VALUE_FULL_INFORMATION *pCtrlInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uPrfType, ULONG uPrfNr, PKEY_VALUE_FULL_INFORMATION *pPrfInf);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS KbdCallOut(PVOID pCtx, PUNICODE_STRING PathName,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE BusType, ULONG uBusNr, PKEY_VALUE_FULL_INFORMATION *pBusInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uCtrlType, ULONG uCtrlNr, PKEY_VALUE_FULL_INFORMATION *pCtrlInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uPrfType, ULONG uPrfNr, PKEY_VALUE_FULL_INFORMATION *pPrfInf);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/* */ NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING RegistryPath);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncRT_C_DECLS_END
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#ifdef ALLOC_PRAGMA
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,CreateResList)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,MouFindWheel)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,KbdInitHw)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,KbdGetRegstry)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,KbdCallOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,MouInitHw)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,MouGetRegstry)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,MouCallOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,InitHw)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,HwGetRegstry)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#pragma alloc_text(INIT,DriverEntry)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#endif
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN MouDataToQueue(PPORTMOUEXT MouExt, PMOUSE_INPUT_DATA InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( MouExt->DataIn == MouExt->DataOut
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && MouExt->cInput)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(MouExt->DataIn) = *InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouExt->cInput++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouExt->DataIn++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (MouExt->DataIn == MouExt->DataEnd)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouExt->DataIn = MouExt->InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN KbdDataToQueue(PPORTKBDEXT KbdExt, PKEYBOARD_INPUT_DATA InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_INPUT_DATA previousDataIn;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( KbdExt->DataIn == KbdExt->DataOut
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && KbdExt->cInput)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (KbdExt->DataIn == KbdExt->InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync previousDataIn = KbdExt->DataEnd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync previousDataIn = KbdExt->DataIn - 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync previousDataIn->MakeCode = KEYBOARD_OVERRUN_MAKE_CODE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync previousDataIn->Flags = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(KbdExt->DataIn) = *InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdExt->cInput++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdExt->DataIn++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (KbdExt->DataIn == KbdExt->DataEnd)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdExt->DataIn = KbdExt->InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Queues the current input data to be processed by a DPC outside the ISR
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID QueueInput(PDEVICE_OBJECT pDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouseEnableCount)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.UnitId = pDevExt->MouExt.UnitId;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!MouDataToQueue(&pDevExt->MouExt, &pDevExt->MouExt.CurrentInput))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->DpcInterlockMouse >= 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->DpcInterlockMouse++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInsertQueueDpc(&pDevExt->MouseIsrDpc, pDevObj->CurrentIrp, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Drain the i8042 controller buffer.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID DrainOutBuf(PUCHAR DataAddress, PUCHAR CommandAddress)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < 2000; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!(I8X_GET_STATUS_BYTE(CommandAddress) & INPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(500);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while (I8X_GET_STATUS_BYTE(CommandAddress) & OUTPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync byte = I8X_GET_DATA_BYTE(DataAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Read a data byte from the controller, keyboard or mouse in polling mode.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS GetBytePoll(int DevType, PDEVEXT pDevExt, PUCHAR Byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG i = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR fMask = (DevType == MouDevType) ? (UCHAR)(OUTPUT_BUFFER_FULL | MOUSE_OUTPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : (UCHAR) OUTPUT_BUFFER_FULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while ( (i < (ULONG)pDevExt->Cfg.PollingIterations)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && ((UCHAR)((byte = I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd])) & fMask) != fMask))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte & OUTPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *Byte = I8X_GET_DATA_BYTE(pDevExt->DevRegs[i8042Dat]);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(pDevExt->Cfg.StallMicroseconds);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync i++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (i >= (ULONG)pDevExt->Cfg.PollingIterations)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_IO_TIMEOUT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *Byte = I8X_GET_DATA_BYTE(pDevExt->DevRegs[i8042Dat]);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Send a command or data byte to the controller, keyboard or mouse.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS PutBytePoll(CCHAR PortType, BOOLEAN fWaitForAck, int AckDevType, PDEVEXT pDevExt, UCHAR Byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (AckDevType == MouDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* switch to AUX device */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_WRITE_TO_AUXILIARY_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUCHAR dataAddress = pDevExt->DevRegs[i8042Dat];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUCHAR commandAddress = pDevExt->DevRegs[i8042Cmd];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned j = 0; j < (unsigned)pDevExt->Cfg.iResend; j++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync unsigned i = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while ( i++ < (ULONG)pDevExt->Cfg.PollingIterations
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && (I8X_GET_STATUS_BYTE(commandAddress) & INPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(pDevExt->Cfg.StallMicroseconds);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (i >= (ULONG)pDevExt->Cfg.PollingIterations)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_IO_TIMEOUT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DrainOutBuf(dataAddress, commandAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (PortType == i8042Cmd)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8X_PUT_COMMAND_BYTE(commandAddress, Byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8X_PUT_DATA_BYTE(dataAddress, Byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!fWaitForAck)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fKeepTrying = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while ((status = GetBytePoll(AckDevType, pDevExt, &byte)) == STATUS_SUCCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte == ACKNOWLEDGE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (byte == RESEND)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (AckDevType == MouDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_WRITE_TO_AUXILIARY_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fKeepTrying = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!fKeepTrying)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_IO_TIMEOUT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Read a byte from controller, keyboard or mouse
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID GetByteAsync(int DevType, PDEVEXT pDevExt, PUCHAR pByte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR fMask;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG i = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fMask = (DevType == MouDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ? (UCHAR) (OUTPUT_BUFFER_FULL | MOUSE_OUTPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : (UCHAR) OUTPUT_BUFFER_FULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while ( i < (ULONG)pDevExt->Cfg.PollingIterations
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && ((UCHAR)((byte = I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd])) & fMask) != fMask))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte & OUTPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pByte = I8X_GET_DATA_BYTE(pDevExt->DevRegs[i8042Dat]);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync i++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (i >= (ULONG)pDevExt->Cfg.PollingIterations)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pByte = I8X_GET_DATA_BYTE(pDevExt->DevRegs[i8042Dat]);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Send a command or data byte to the controller, keyboard or mouse
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * asynchronously.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID PutByteAsync(CCHAR PortType, PDEVEXT pDevExt, UCHAR Byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync unsigned i = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while (I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd]) & INPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (i++ >= (ULONG)pDevExt->Cfg.PollingIterations)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (PortType == i8042Cmd)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8X_PUT_COMMAND_BYTE(pDevExt->DevRegs[i8042Cmd], Byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8X_PUT_DATA_BYTE(pDevExt->DevRegs[i8042Dat], Byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Initiaze an I/O operation for the keyboard device.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID KbdStartIO(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->TimerCount = 3;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KBDSETPACKET keyboardPacket = pDevExt->KbdExt.CurrentOutput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KbdExt.CurrentOutput.State == SendFirstByte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutByteAsync(i8042Dat, pDevExt, keyboardPacket.FirstByte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->KbdExt.CurrentOutput.State == SendLastByte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutByteAsync(i8042Dat, pDevExt, keyboardPacket.LastByte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN KbdStartWrapper(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj = ((PKBDINITIATECTX)pCtx)->pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.State = SendFirstByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.FirstByte = ((PKBDINITIATECTX)pCtx)->FirstByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.LastByte = ((PKBDINITIATECTX)pCtx)->LastByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ResendCount = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdStartIO(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN DecTimer(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PTIMERCTX pTmCtx = (PTIMERCTX)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj = pTmCtx->pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (*(pTmCtx->TimerCounter) != -1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*(pTmCtx->TimerCounter))--;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pTmCtx->NewTimerCount = *(pTmCtx->TimerCounter);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (*(pTmCtx->TimerCounter) == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.State = Idle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ResendCount = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Perform an operation on the InterlockedDpcVariable.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN DpcVarOp(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVAROPCTX pOpCtx = (PVAROPCTX)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (pOpCtx->Operation)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IncrementOperation:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pOpCtx->VariableAddress)++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case DecrementOperation:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pOpCtx->VariableAddress)--;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case WriteOperation:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pOpCtx->VariableAddress = *pOpCtx->NewValue;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(pOpCtx->NewValue) = *(pOpCtx->VariableAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN GetDataQueuePtr(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)((PGETDATAPTRCTX)pCtx)->pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CCHAR DevType = (CCHAR)((PGETDATAPTRCTX)pCtx)->DevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (DevType == KbdDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PGETDATAPTRCTX)pCtx)->DataIn = pDevExt->KbdExt.DataIn;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PGETDATAPTRCTX)pCtx)->DataOut = pDevExt->KbdExt.DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PGETDATAPTRCTX)pCtx)->cInput = pDevExt->KbdExt.cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (DevType == MouDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PGETDATAPTRCTX)pCtx)->DataIn = pDevExt->MouExt.DataIn;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PGETDATAPTRCTX)pCtx)->DataOut = pDevExt->MouExt.DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PGETDATAPTRCTX)pCtx)->cInput = pDevExt->MouExt.cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN InitDataQueue(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)((PI8042INITDATACTX)pCtx)->pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CCHAR DevType = (CCHAR) ((PI8042INITDATACTX)pCtx)->DevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (DevType == KbdDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.cInput = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.DataIn = pDevExt->KbdExt.InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.DataOut = pDevExt->KbdExt.InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (DevType == MouDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.cInput = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.DataIn = pDevExt->MouExt.InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.DataOut = pDevExt->MouExt.InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN SetDataQueuePtr(PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)((PSETDATAPTRCTX)pCtx)->pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CCHAR DevType = (CCHAR) ((PSETDATAPTRCTX)pCtx)->DevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (DevType == KbdDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.DataOut = (PKEYBOARD_INPUT_DATA)((PSETDATAPTRCTX)pCtx)->DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.cInput -= ((PSETDATAPTRCTX)pCtx)->cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (DevType == MouDevType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.DataOut = (PMOUSE_INPUT_DATA)((PSETDATAPTRCTX)pCtx)->DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.cInput -= ((PSETDATAPTRCTX)pCtx)->cInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * DISPATCH_LEVEL IRQL: Complete requests.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CompleteDpc(PKDPC Dpc, PDEVICE_OBJECT pDevObj, PIRP Irp, PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Dpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeCancelTimer(&pDevExt->CommandTimer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp = pDevObj->CurrentIrp;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_SET_INDICATORS:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdInd = *(PKEYBOARD_INDICATOR_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_SET_TYPEMATIC:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KeyRepeatCurrent = *(PKEYBOARD_TYPEMATIC_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest (Irp, IO_KEYBOARD_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS I8042Flush(PDEVICE_OBJECT pDevObj, PIRP Irp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_NOT_IMPLEMENTED;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Dispatch internal device control requests.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS I8042DevCtrl(PDEVICE_OBJECT pDevObj, PIRP Irp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8042INITDATACTX initDataCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVOID pParams;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_ATTRIBUTES KbdAttr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cbTrans;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_KEYBOARD_CONNECT:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) != KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_NO_SUCH_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->KbdExt.ConnectData.ClassService)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SHARING_VIOLATION;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INVALID_PARAMETER;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ConnectData = *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.DevType = KbdDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, InitDataQueue, &initDataCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_MOUSE_CONNECT:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT) != MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_NO_SUCH_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->MouExt.ConnectData.ClassService)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SHARING_VIOLATION;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INVALID_PARAMETER;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.ConnectData = *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.DevType = MouDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, InitDataQueue, &initDataCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_MOUSE_DISCONNECT:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_NOT_IMPLEMENTED;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_KEYBOARD_ENABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_KEYBOARD_DISABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_MOUSE_ENABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_MOUSE_DISABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_PENDING;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_ATTRIBUTES))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_BUFFER_TOO_SMALL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(PKEYBOARD_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer = pDevExt->Cfg.KbdAttr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = sizeof(KEYBOARD_ATTRIBUTES);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cbTrans = sizeof(KEYBOARD_INDICATOR_TRANSLATION)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync + (sizeof(INDICATOR_LIST) * (pDevExt->Cfg.KbdAttr.NumberOfIndicators - 1));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < cbTrans)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_BUFFER_TOO_SMALL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PKEYBOARD_INDICATOR_TRANSLATION)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->AssociatedIrp.SystemBuffer)->NumberOfIndicatorKeys = pDevExt->Cfg.KbdAttr.NumberOfIndicators;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlMoveMemory(((PKEYBOARD_INDICATOR_TRANSLATION)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->AssociatedIrp.SystemBuffer)->IndicatorList, (PCHAR)s_aIndicators, cbTrans);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = cbTrans;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_QUERY_INDICATORS:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_BUFFER_TOO_SMALL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(PKEYBOARD_INDICATOR_PARAMETERS)Irp->AssociatedIrp.SystemBuffer = pDevExt->Cfg.KbdInd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_SET_INDICATORS:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || ( (((PKEYBOARD_INDICATOR_PARAMETERS)Irp->AssociatedIrp.SystemBuffer)->LedFlags
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync & ~(KEYBOARD_SCROLL_LOCK_ON | KEYBOARD_NUM_LOCK_ON | KEYBOARD_CAPS_LOCK_ON)) != 0))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INVALID_PARAMETER;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_PENDING;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_BUFFER_TOO_SMALL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(PKEYBOARD_TYPEMATIC_PARAMETERS)Irp->AssociatedIrp.SystemBuffer = pDevExt->Cfg.KeyRepeatCurrent;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = sizeof(KEYBOARD_TYPEMATIC_PARAMETERS);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_SET_TYPEMATIC:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pParams = Irp->AssociatedIrp.SystemBuffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdAttr = &pDevExt->Cfg.KbdAttr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || ((PKEYBOARD_TYPEMATIC_PARAMETERS)pParams)->Rate < KbdAttr->KeyRepeatMinimum.Rate
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || ((PKEYBOARD_TYPEMATIC_PARAMETERS)pParams)->Rate > KbdAttr->KeyRepeatMaximum.Rate
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || ((PKEYBOARD_TYPEMATIC_PARAMETERS)pParams)->Delay < KbdAttr->KeyRepeatMinimum.Delay
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || ((PKEYBOARD_TYPEMATIC_PARAMETERS)pParams)->Delay > KbdAttr->KeyRepeatMaximum.Delay)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INVALID_PARAMETER;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_PENDING;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_MOUSE_QUERY_ATTRIBUTES:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_BUFFER_TOO_SMALL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *(PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer = pDevExt->Cfg.MouAttr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INVALID_DEVICE_REQUEST;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status == STATUS_PENDING)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoMarkIrpPending(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartPacket(pDevObj, Irp, (PULONG)NULL, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(Irp, IO_NO_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Dispatch routine for create/open and close requests.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS I8042OpenClose(PDEVICE_OBJECT pDevObj, PIRP Irp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Information = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(Irp, IO_NO_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * DISPATCH_LEVEL IRQL: Complete requests that have exceeded the maximum
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * number of retries.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CtrlRetriesExceededDpc(PKDPC Dpc, PDEVICE_OBJECT pDevObj, PIRP Irp, PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Dpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest (Irp, IO_KEYBOARD_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic UCHAR TypematicPeriod[] =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync 31, 31, 28, 26, 23, 20, 18, 17, 15, 13, 12, 11, 10, 9,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync};
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Convert typematic rate/delay to a value expected by the keyboard:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * - bit 7 is zero
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * - bits 5...6 indicate the delay
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * - bits 0...4 indicate the rate
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic UCHAR ConvertTypematic(USHORT Rate, USHORT Delay)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR value = (UCHAR) ((Delay / 250) - 1);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync value <<= 5;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (Rate <= 27)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync value |= TypematicPeriod[Rate];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return value;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Start an I/O operation for the device.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID I8042StartIo(PDEVICE_OBJECT pDevObj, PIRP Irp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KBDINITIATECTX keyboardInitiateContext;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER deltaTime;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_KEYBOARD_ENABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync interlockedResult = ASMAtomicIncU32(&pDevExt->KeyboardEnableCount);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_KEYBOARD_DISABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KeyboardEnableCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASMAtomicDecU32(&pDevExt->KeyboardEnableCount);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_MOUSE_ENABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASMAtomicIncU32(&pDevExt->MouseEnableCount);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_INTERNAL_MOUSE_DISABLE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouseEnableCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASMAtomicDecU32(&pDevExt->MouseEnableCount);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Irp->IoStatus.Status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_SET_INDICATORS:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync keyboardInitiateContext.pDevObj = pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync keyboardInitiateContext.FirstByte = SET_KEYBOARD_INDICATORS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync keyboardInitiateContext.LastByte =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (UCHAR) ((PKEYBOARD_INDICATOR_PARAMETERS)Irp->AssociatedIrp.SystemBuffer)->LedFlags;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, KbdStartWrapper, &keyboardInitiateContext);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.HighPart = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSetTimer(&pDevExt->CommandTimer, deltaTime, &pDevExt->TimeOutDpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case IOCTL_KEYBOARD_SET_TYPEMATIC:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync keyboardInitiateContext.pDevObj = pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync keyboardInitiateContext.FirstByte = SET_KEYBOARD_TYPEMATIC;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync keyboardInitiateContext.LastByte =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ConvertTypematic(((PKEYBOARD_TYPEMATIC_PARAMETERS)Irp->AssociatedIrp.SystemBuffer)->Rate,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ((PKEYBOARD_TYPEMATIC_PARAMETERS)Irp->AssociatedIrp.SystemBuffer)->Delay);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, KbdStartWrapper, &keyboardInitiateContext);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.HighPart = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSetTimer(&pDevExt->CommandTimer, deltaTime, &pDevExt->TimeOutDpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Driver's command timeout routine.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CtrlTimeoutDpc(PKDPC Dpc, PDEVICE_OBJECT pDevObj, PVOID SystemContext1, PVOID SystemContext2)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KIRQL cancelIrql;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoAcquireCancelSpinLock(&cancelIrql);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PIRP irp = pDevObj->CurrentIrp;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!irp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoReleaseCancelSpinLock(cancelIrql);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoSetCancelRoutine(irp, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoReleaseCancelSpinLock(cancelIrql);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync TIMERCTX timerContext;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync timerContext.pDevObj = pDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync timerContext.TimerCounter = &pDevExt->TimerCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, DecTimer, &timerContext);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (timerContext.NewTimerCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevObj->CurrentIrp->IoStatus.Information = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevObj->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoStartNextPacket(pDevObj, FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoCompleteRequest(irp, IO_KEYBOARD_INCREMENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER deltaTime;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.HighPart = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSetTimer(&pDevExt->CommandTimer, deltaTime, &pDevExt->TimeOutDpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * DISPATCH_LEVEL IRQL: Finish processing for keyboard interrupts.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CtrlKbdIsrDpc(PKDPC Dpc, PDEVICE_OBJECT pDevObj, PIRP Irp, PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Dpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VAROPCTX opCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.VariableAddress = &pDevExt->DpcInterlockKeyboard;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = IncrementOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, DpcVarOp, (PVOID)&opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fContinue = (interlockedResult == 0) ? TRUE : FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while (fContinue)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cbNotConsumed = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG inputDataConsumed = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GETDATAPTRCTX getPtrCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync getPtrCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync getPtrCtx.DevType = KbdDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SETDATAPTRCTX setPtrCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DevType = KbdDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.cInput = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, GetDataQueuePtr, &getPtrCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (getPtrCtx.cInput)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVOID classDeviceObject = pDevExt->KbdExt.ConnectData.ClassDeviceObject;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PSERVICECALLBACK classService = pDevExt->KbdExt.ConnectData.ClassService;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(classService);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (getPtrCtx.DataOut >= getPtrCtx.DataIn)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync classService(classDeviceObject, getPtrCtx.DataOut, pDevExt->KbdExt.DataEnd, &inputDataConsumed);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cbNotConsumed = (((PUCHAR) pDevExt->KbdExt.DataEnd - (PUCHAR) getPtrCtx.DataOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync / sizeof(KEYBOARD_INPUT_DATA)) - inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.cInput += inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (cbNotConsumed)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DataOut = ((PUCHAR)getPtrCtx.DataOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync + (inputDataConsumed * sizeof(KEYBOARD_INPUT_DATA));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DataOut = pDevExt->KbdExt.InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync getPtrCtx.DataOut = setPtrCtx.DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( cbNotConsumed == 0
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && inputDataConsumed < getPtrCtx.cInput)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync classService(classDeviceObject, getPtrCtx.DataOut, getPtrCtx.DataIn, &inputDataConsumed);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cbNotConsumed = (((PUCHAR) getPtrCtx.DataIn - (PUCHAR) getPtrCtx.DataOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync / sizeof(KEYBOARD_INPUT_DATA)) - inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DataOut = ((PUCHAR)getPtrCtx.DataOut) +
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (inputDataConsumed * sizeof(KEYBOARD_INPUT_DATA));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.cInput += inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, SetDataQueuePtr, &setPtrCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (cbNotConsumed)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = WriteOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync interlockedResult = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER deltaTime;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.HighPart = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSetTimer(&pDevExt->KbdExt.DataConsumptionTimer, deltaTime, &pDevExt->KeyboardIsrDpcRetry);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fContinue = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = DecrementOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (interlockedResult != -1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = WriteOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync interlockedResult = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->KbdIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fContinue = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * DISPATCH_LEVEL IRQL: Finish processing of mouse interrupts
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CtrlMouIsrDpc(PKDPC Dpc, PDEVICE_OBJECT pDevObj, PIRP Irp, PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Dpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Irp);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VAROPCTX opCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LONG interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.VariableAddress = &pDevExt->DpcInterlockMouse;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = IncrementOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fContinue = (interlockedResult == 0) ? TRUE : FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync while (fContinue)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cbNotConsumed = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG inputDataConsumed = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GETDATAPTRCTX getPtrCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync getPtrCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync getPtrCtx.DevType = MouDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SETDATAPTRCTX setPtrCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DevType = MouDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.cInput = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, GetDataQueuePtr, &getPtrCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (getPtrCtx.cInput)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PVOID classDeviceObject = pDevExt->MouExt.ConnectData.ClassDeviceObject;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PSERVICECALLBACK classService = pDevExt->MouExt.ConnectData.ClassService;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(classService);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (getPtrCtx.DataOut >= getPtrCtx.DataIn)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync classService(classDeviceObject, getPtrCtx.DataOut, pDevExt->MouExt.DataEnd, &inputDataConsumed);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cbNotConsumed = (((PUCHAR)pDevExt->MouExt.DataEnd - (PUCHAR) getPtrCtx.DataOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.cInput += inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (cbNotConsumed)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DataOut = ((PUCHAR)getPtrCtx.DataOut) + (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DataOut = pDevExt->MouExt.InputData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync getPtrCtx.DataOut = setPtrCtx.DataOut;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( cbNotConsumed == 0
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && inputDataConsumed < getPtrCtx.cInput)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync classService(classDeviceObject, getPtrCtx.DataOut, getPtrCtx.DataIn, &inputDataConsumed);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cbNotConsumed = (((PUCHAR) getPtrCtx.DataIn - (PUCHAR) getPtrCtx.DataOut)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.DataOut = ((PUCHAR)getPtrCtx.DataOut) + (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync setPtrCtx.cInput += inputDataConsumed;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, SetDataQueuePtr, &setPtrCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (cbNotConsumed)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = WriteOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync interlockedResult = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER deltaTime;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync deltaTime.HighPart = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSetTimer(&pDevExt->MouExt.DataConsumptionTimer, deltaTime, &pDevExt->MouseIsrDpcRetry);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fContinue = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = DecrementOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (interlockedResult != -1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.Operation = WriteOperation;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync interlockedResult = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync opCtx.NewValue = &interlockedResult;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeSynchronizeExecution(pDevExt->MouIntObj, DpcVarOp, &opCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fContinue = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Interrupt service routine for the mouse device.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN MouIntHandler(PKINTERRUPT Interrupt, PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR uPrevSignAndOverflow;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Interrupt);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd]) & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(10);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd]) & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GetByteAsync(MouDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( pDevExt->MouExt.LastByteReceived == 0xaa
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && byte == 0x00)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent &= ~WHEELMOUSE_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouAttr.NumberOfButtons = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutByteAsync(i8042Cmd, pDevExt, I8042_WRITE_TO_AUXILIARY_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutByteAsync(i8042Dat, pDevExt, ENABLE_MOUSE_TRANSMISSION);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseExpectingACK;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.LastByteReceived = byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER tickDelta, newTick;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeQueryTickCount(&newTick);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync tickDelta.QuadPart = newTick.QuadPart - pDevExt->MouExt.PreviousTick.QuadPart;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( pDevExt->MouExt.InputState != MouseIdle
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && pDevExt->MouExt.InputState != MouseExpectingACK
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && (tickDelta.LowPart >= pDevExt->MouExt.SynchTickCount || tickDelta.HighPart != 0))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseIdle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.PreviousTick = newTick;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (pDevExt->MouExt.InputState)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case MouseIdle:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR fPrevBtns = pDevExt->MouExt.PreviousButtons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonData = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((!(fPrevBtns & LEFT_BUTTON_DOWN)) && (byte & LEFT_BUTTON_DOWN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if ((fPrevBtns & LEFT_BUTTON_DOWN) && !(byte & LEFT_BUTTON_DOWN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((!(fPrevBtns & RIGHT_BUTTON_DOWN)) && (byte & RIGHT_BUTTON_DOWN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if ((fPrevBtns & RIGHT_BUTTON_DOWN) && !(byte & RIGHT_BUTTON_DOWN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((!(fPrevBtns & MIDDLE_BUTTON_DOWN)) && (byte & MIDDLE_BUTTON_DOWN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if ((fPrevBtns & MIDDLE_BUTTON_DOWN) && !(byte & MIDDLE_BUTTON_DOWN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.PreviousButtons = byte & (RIGHT_BUTTON_DOWN|MIDDLE_BUTTON_DOWN|LEFT_BUTTON_DOWN);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.uCurrSignAndOverflow = (UCHAR) (byte & MOUSE_SIGN_OVERFLOW_MASK);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = XMovement;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case XMovement:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.uCurrSignAndOverflow & X_OVERFLOW)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync uPrevSignAndOverflow = pDevExt->MouExt.uPrevSignAndOverflow;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (uPrevSignAndOverflow & X_OVERFLOW)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((uPrevSignAndOverflow & X_DATA_SIGN) != (pDevExt->MouExt.uCurrSignAndOverflow & X_DATA_SIGN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.uCurrSignAndOverflow ^= X_DATA_SIGN;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.uCurrSignAndOverflow & X_DATA_SIGN)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastX = MOUSE_MAXIMUM_NEGATIVE_DELTA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastX = MOUSE_MAXIMUM_POSITIVE_DELTA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastX = (ULONG) byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.uCurrSignAndOverflow & X_DATA_SIGN)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastX |= MOUSE_MAXIMUM_NEGATIVE_DELTA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = YMovement;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case YMovement:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.uCurrSignAndOverflow & Y_OVERFLOW)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync uPrevSignAndOverflow = pDevExt->MouExt.uPrevSignAndOverflow;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (uPrevSignAndOverflow & Y_OVERFLOW)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((uPrevSignAndOverflow & Y_DATA_SIGN) != (pDevExt->MouExt.uCurrSignAndOverflow & Y_DATA_SIGN))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.uCurrSignAndOverflow ^= Y_DATA_SIGN;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.uCurrSignAndOverflow & Y_DATA_SIGN)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY = MOUSE_MAXIMUM_POSITIVE_DELTA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY = MOUSE_MAXIMUM_NEGATIVE_DELTA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY = (ULONG) byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.uCurrSignAndOverflow & Y_DATA_SIGN)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY |= MOUSE_MAXIMUM_NEGATIVE_DELTA;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY = -pDevExt->MouExt.CurrentInput.LastY;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.uPrevSignAndOverflow = pDevExt->MouExt.uCurrSignAndOverflow;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & WHEELMOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = ZMovement;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.Flags = MOUSE_MOVE_RELATIVE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VMMDevReqMouseStatus *pReq = pDevExt->pReq;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pReq)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync int rc = VbglGRPerform (&pReq->header);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (RT_SUCCESS(rc))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pReq->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* make it an absolute move */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.Flags = MOUSE_MOVE_ABSOLUTE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastX = pReq->pointerXPos;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY = pReq->pointerYPos;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Log(("VBoxMouseNT: ERROR querying mouse capabilities from VMMDev. rc = %Rrc\n", rc));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync QueueInput(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseIdle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case ZMovement:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#if 0
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte && pDevExt->MouExt.CurrentInput.Buttons == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#endif
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte & 0x80)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonData = 0x0078;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonData = 0xFF88;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.ButtonFlags |= MOUSE_WHEEL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.Flags = MOUSE_MOVE_RELATIVE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VMMDevReqMouseStatus *pReq = pDevExt->pReq;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pReq)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync int rc = VbglGRPerform(&pReq->header);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (RT_SUCCESS(rc))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pReq->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* make it an absolute move */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.Flags = MOUSE_MOVE_ABSOLUTE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastX = pReq->pointerXPos;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.CurrentInput.LastY = pReq->pointerYPos;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Log(("VBoxMouseNT: ERROR querying mouse capabilities from VMMDev. rc = %Rrc\n", rc));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync QueueInput(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseIdle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case MouseExpectingACK:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte == ACKNOWLEDGE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseIdle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (byte == RESEND)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutByteAsync(i8042Cmd, pDevExt, I8042_WRITE_TO_AUXILIARY_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutByteAsync(i8042Dat, pDevExt, ENABLE_MOUSE_TRANSMISSION);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Interrupt service routine.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic BOOLEAN KbdIntHandler(PKINTERRUPT Interrupt, PVOID pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(Interrupt);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd]) & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync != OUTPUT_BUFFER_FULL)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < (ULONG)pDevExt->Cfg.PollStatusIterations; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(1);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd]) & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync == (OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((I8X_GET_STATUS_BYTE(pDevExt->DevRegs[i8042Cmd]) & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync != (OUTPUT_BUFFER_FULL))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KeyboardEnableCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR scanCode = I8X_GET_DATA_BYTE(pDevExt->DevRegs[i8042Dat]);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR scanCode;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GetByteAsync(KbdDevType, pDevExt, &scanCode);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (scanCode)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case RESEND:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->TimerCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->TimerCount = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( pDevExt->KbdExt.CurrentOutput.State==Idle
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || !pDevObj->CurrentIrp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto ScanCodeCase;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->KbdExt.ResendCount < pDevExt->Cfg.iResend)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ResendCount++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdStartIO(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.State = Idle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInsertQueueDpc(&pDevExt->RetriesExceededDpc, pDevObj->CurrentIrp, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case ACKNOWLEDGE:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->TimerCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->TimerCount = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ResendCount = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KbdExt.CurrentOutput.State == SendFirstByte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.State = SendLastByte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdStartIO(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->KbdExt.CurrentOutput.State == SendLastByte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.State = Idle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoRequestDpc(pDevObj, pDevObj->CurrentIrp, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ScanCodeCase:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_INPUT_DATA input = &pDevExt->KbdExt.CurrentInput;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KBDSCANSTATE *pScanState = &pDevExt->KbdExt.CurrentScanState;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (scanCode == (UCHAR) 0xFF)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->MakeCode = KEYBOARD_OVERRUN_MAKE_CODE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->Flags = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pScanState = Normal;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (*pScanState)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case Normal:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (scanCode == (UCHAR) 0xE0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->Flags |= KEY_E0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pScanState = GotE0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (scanCode == (UCHAR) 0xE1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->Flags |= KEY_E1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pScanState = GotE1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* fall through */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case GotE0:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case GotE1:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (scanCode > 0x7F)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->MakeCode = scanCode & 0x7F;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->Flags |= KEY_BREAK;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->MakeCode = scanCode;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pScanState = Normal;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (*pScanState == Normal)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KeyboardEnableCount)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentInput.UnitId = pDevExt->KbdExt.UnitId;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!KbdDataToQueue(&pDevExt->KbdExt, input))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pDevExt->DpcInterlockKeyboard >= 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->DpcInterlockKeyboard++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInsertQueueDpc(&pDevExt->KeyboardIsrDpc, pDevObj->CurrentIrp, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync input->Flags = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouEnableTrans(PDEVICE_OBJECT pDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, FALSE /*=wait*/, MouDevType, pDevExt, ENABLE_MOUSE_TRANSMISSION);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Configuration information for the keyboard.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID KbdGetRegstry(PINITEXT pInit, PUNICODE_STRING RegistryPath,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUNICODE_STRING KeyboardDeviceName, PUNICODE_STRING PointerDeviceName)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = &pInit->DevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < MaximumInterfaceType; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE interfaceType = (INTERFACE_TYPE)i;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE controllerType = KeyboardController;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE peripheralType = KeyboardPeripheral;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = IoQueryDeviceDescription(&interfaceType, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &controllerType, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &peripheralType, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdCallOut, pInit);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync HwGetRegstry(pInit, RegistryPath, KeyboardDeviceName, PointerDeviceName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PI8042CFGINF pCfg = &pInit->DevExt.Cfg;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_ID keyboardId = &pCfg->KbdAttr.KeyboardIdentifier;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!ENHANCED_KEYBOARD(*keyboardId))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollingIterations = pCfg->PollingIterationsMaximum;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.NumberOfFunctionKeys = s_aKeybType[keyboardId->Type-1].cFunctionKeys;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.NumberOfIndicators = s_aKeybType[keyboardId->Type-1].cIndicators;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.NumberOfKeysTotal = s_aKeybType[keyboardId->Type-1].cKeysTotal;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardMode = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyRepeatMinimum.Rate = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyRepeatMinimum.Delay = 250;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyRepeatMaximum.Rate = 30;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyRepeatMaximum.Delay = 1000;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KeyRepeatCurrent.Rate = 30;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KeyRepeatCurrent.Delay = 250;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Retrieve the configuration information for the mouse.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID MouGetRegstry(PINITEXT pInit, PUNICODE_STRING RegistryPath,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUNICODE_STRING KeyboardDeviceName, PUNICODE_STRING PointerDeviceName)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = &pInit->DevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE interfaceType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE controllerType = PointerController;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE peripheralType = PointerPeripheral;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < MaximumInterfaceType; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync interfaceType = (INTERFACE_TYPE)i;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = IoQueryDeviceDescription(&interfaceType, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &controllerType, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &peripheralType, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouCallOut, pInit);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pInit->DevExt.HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!(pInit->DevExt.HardwarePresent & KEYBOARD_HARDWARE_PRESENT))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync HwGetRegstry(pInit, RegistryPath, KeyboardDeviceName, PointerDeviceName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pInit->DevExt.Cfg.MouAttr.MouseIdentifier = MOUSE_I8042_HARDWARE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Initialize the driver.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncNTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING RegistryPath)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVICE_OBJECT pPortDevObj = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KIRQL IrqlCoord = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG IntVecKbd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG IntVecMou;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KIRQL IrqlKbd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KIRQL IrqlMou;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KAFFINITY AffKbd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KAFFINITY AffMou;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG addressSpace;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PHYSICAL_ADDRESS Phys;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fConflict;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING KbdNameFull;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING MouNameFull;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING KbdNameBase;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING MouNameBase;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING DevNameSuff;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING resourceDeviceClass;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING registryPath;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync#define NAME_MAX 256
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync WCHAR keyboardBuffer[NAME_MAX];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync WCHAR pointerBuffer[NAME_MAX];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LogFlow(("VBoxMouseNT::DriverEntry: enter\n"));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PINITEXT pInit = (PINITEXT)ExAllocatePool(NonPagedPool, sizeof(INITEXT));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!pInit)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(pInit, sizeof(INITEXT));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameFull.MaximumLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameFull.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameFull.MaximumLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameFull.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DevNameSuff.MaximumLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DevNameSuff.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync resourceDeviceClass.MaximumLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync resourceDeviceClass.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync registryPath.MaximumLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(keyboardBuffer, NAME_MAX * sizeof(WCHAR));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameBase.Buffer = keyboardBuffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameBase.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameBase.MaximumLength = NAME_MAX * sizeof(WCHAR);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(pointerBuffer, NAME_MAX * sizeof(WCHAR));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameBase.Buffer = pointerBuffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameBase.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameBase.MaximumLength = NAME_MAX * sizeof(WCHAR);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync registryPath.Buffer = (PWSTR)ExAllocatePool(PagedPool, RegistryPath->Length + sizeof(UNICODE_NULL));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!registryPath.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync registryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync registryPath.MaximumLength = registryPath.Length;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(registryPath.Buffer, registryPath.Length);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlMoveMemory(registryPath.Buffer, RegistryPath->Buffer, RegistryPath->Length);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdGetRegstry(pInit, &registryPath, &KbdNameBase, &MouNameBase);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouGetRegstry(pInit, &registryPath, &KbdNameBase, &MouNameBase);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pInit->DevExt.HardwarePresent == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_NO_SUCH_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (!(pInit->DevExt.HardwarePresent & KEYBOARD_HARDWARE_PRESENT))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_NO_SUCH_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&DevNameSuff, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DevNameSuff.MaximumLength = (KEYBOARD_PORTS_MAXIMUM > POINTER_PORTS_MAXIMUM)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ? KEYBOARD_PORTS_MAXIMUM * sizeof(WCHAR)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : POINTER_PORTS_MAXIMUM * sizeof(WCHAR);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DevNameSuff.MaximumLength += sizeof(UNICODE_NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DevNameSuff.Buffer = (PWSTR)ExAllocatePool(PagedPool, DevNameSuff.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!DevNameSuff.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(DevNameSuff.Buffer, DevNameSuff.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&KbdNameFull, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameFull.MaximumLength = sizeof(L"\\Device\\") + KbdNameBase.Length + DevNameSuff.MaximumLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameFull.Buffer = (PWSTR)ExAllocatePool(PagedPool, KbdNameFull.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!KbdNameFull.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(KbdNameFull.Buffer, KbdNameFull.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&KbdNameFull, L"\\Device\\");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&KbdNameFull, KbdNameBase.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < KEYBOARD_PORTS_MAXIMUM; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = RtlIntegerToUnicodeString(i, 10, &DevNameSuff);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeStringToString(&KbdNameFull, &DevNameSuff);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LogFlow(("VBoxMouseNT::DriverEntry: Creating device object named %S\n", KbdNameFull.Buffer));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = IoCreateDevice(pDrvObj, sizeof(DEVEXT), &KbdNameFull,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync FILE_DEVICE_8042_PORT, 0, FALSE, &pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameFull.Length -= DevNameSuff.Length;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pPortDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pDevExt = pInit->DevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->pDevObj = pPortDevObj;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG resourceListSize = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_RESOURCE_LIST resources = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CreateResList(pDevExt, &resources, &resourceListSize);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&resourceDeviceClass, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync resourceDeviceClass.MaximumLength = KbdNameBase.Length + sizeof(L"/") + MouNameBase.Length;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync resourceDeviceClass.Buffer = (PWSTR)ExAllocatePool(PagedPool, resourceDeviceClass.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!resourceDeviceClass.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(resourceDeviceClass.Buffer, resourceDeviceClass.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeStringToString(&resourceDeviceClass, &KbdNameBase);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&resourceDeviceClass, L"/");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeStringToString(&resourceDeviceClass, &MouNameBase);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoReportResourceUsage(&resourceDeviceClass, pDrvObj, NULL, 0, pPortDevObj,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync resources, resourceListSize, FALSE, &fConflict);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (fConflict)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INSUFFICIENT_RESOURCES;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < pDevExt->Cfg.cPorts; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync addressSpace = (pDevExt->Cfg.aPorts[i].Flags & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_IO ? 1 : 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!HalTranslateBusAddress(pDevExt->Cfg.InterfaceType,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.uBusNr,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.aPorts[i].u.Port.Start,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &addressSpace, &Phys))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync addressSpace = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Phys.QuadPart = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!addressSpace)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->fUnmapRegs = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->DevRegs[i] = (PUCHAR)MmMapIoSpace(Phys, pDevExt->Cfg.aPorts[i].u.Port.Length,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (MEMORY_CACHING_TYPE)FALSE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->fUnmapRegs = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->DevRegs[i] = (PUCHAR)Phys.LowPart;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!pDevExt->DevRegs[i])
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_NONE_MAPPED;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pPortDevObj->Flags |= DO_BUFFERED_IO;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync InitHw(pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeSpinLock(&pDevExt->ShIntObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.InputData = (PKEYBOARD_INPUT_DATA)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExAllocatePool(NonPagedPool, pDevExt->Cfg.KbdAttr.InputDataQueueLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!pDevExt->KbdExt.InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INSUFFICIENT_RESOURCES;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.DataEnd =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (PKEYBOARD_INPUT_DATA)((PCHAR) (pDevExt->KbdExt.InputData) + pDevExt->Cfg.KbdAttr.InputDataQueueLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(pDevExt->KbdExt.InputData, pDevExt->Cfg.KbdAttr.InputDataQueueLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&MouNameFull, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameFull.MaximumLength = sizeof(L"\\Device\\") + MouNameBase.Length + DevNameSuff.MaximumLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameFull.Buffer = (PWSTR)ExAllocatePool(PagedPool, MouNameFull.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!MouNameFull.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(MouNameFull.Buffer, MouNameFull.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&MouNameFull, L"\\Device\\");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&MouNameFull, MouNameBase.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(DevNameSuff.Buffer, DevNameSuff.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DevNameSuff.Length = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < POINTER_PORTS_MAXIMUM; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = RtlIntegerToUnicodeString(i, 10, &DevNameSuff);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeStringToString(&MouNameFull, &DevNameSuff);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LogFlow(("VBoxMouseNT::DriverEntry: pointer port name (symbolic link) = %S\n", MouNameFull.Buffer));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = IoCreateSymbolicLink(&MouNameFull, &KbdNameFull);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameFull.Length -= DevNameSuff.Length;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputData =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (PMOUSE_INPUT_DATA)ExAllocatePool(NonPagedPool, pDevExt->Cfg.MouAttr.InputDataQueueLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!pDevExt->MouExt.InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_INSUFFICIENT_RESOURCES;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.DataEnd = (PMOUSE_INPUT_DATA)((PCHAR) (pDevExt->MouExt.InputData) + pDevExt->Cfg.MouAttr.InputDataQueueLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(pDevExt->MouExt.InputData, pDevExt->Cfg.MouAttr.InputDataQueueLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ConnectData.ClassDeviceObject = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.ConnectData.ClassService = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.ConnectData.ClassDeviceObject = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.ConnectData.ClassService = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8042INITDATACTX initDataCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.pDevExt = pDevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.DevType = KbdDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync InitDataQueue(&initDataCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync initDataCtx.DevType = MouDevType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync InitDataQueue(&initDataCtx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->DpcInterlockKeyboard = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->DpcInterlockMouse = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoInitializeDpcRequest(pPortDevObj, CompleteDpc);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeDpc(&pDevExt->RetriesExceededDpc, (PKDEFERRED_ROUTINE)CtrlRetriesExceededDpc, pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeDpc(&pDevExt->KeyboardIsrDpc, (PKDEFERRED_ROUTINE)CtrlKbdIsrDpc, pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeDpc(&pDevExt->KeyboardIsrDpcRetry, (PKDEFERRED_ROUTINE)CtrlKbdIsrDpc, pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeDpc(&pDevExt->MouseIsrDpc, (PKDEFERRED_ROUTINE)CtrlMouIsrDpc, pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeDpc(&pDevExt->MouseIsrDpcRetry, (PKDEFERRED_ROUTINE)CtrlMouIsrDpc, pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeDpc(&pDevExt->TimeOutDpc, (PKDEFERRED_ROUTINE)CtrlTimeoutDpc, pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeTimer(&pDevExt->CommandTimer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->TimerCount = -1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeTimer(&pDevExt->KbdExt.DataConsumptionTimer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeInitializeTimer(&pDevExt->MouExt.DataConsumptionTimer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IntVecKbd = HalGetInterruptVector(pDevExt->Cfg.InterfaceType,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.uBusNr,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdInt.u.Interrupt.Level,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdInt.u.Interrupt.Vector,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &IrqlKbd, &AffKbd);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IntVecMou = HalGetInterruptVector(pDevExt->Cfg.InterfaceType,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.uBusNr,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouInt.u.Interrupt.Level,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouInt.u.Interrupt.Vector,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &IrqlMou, &AffMou);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( (pDevExt->HardwarePresent & (KEYBOARD_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync == (KEYBOARD_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IrqlCoord = IrqlKbd > IrqlMou ? IrqlKbd : IrqlMou;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = IoConnectInterrupt(&pDevExt->MouIntObj, MouIntHandler, pPortDevObj,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &pDevExt->ShIntObj, IntVecMou, IrqlMou,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (KIRQL) ((IrqlCoord == (KIRQL)0) ? IrqlMou : IrqlCoord),
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouInt.Flags == CM_RESOURCE_INTERRUPT_LATCHED
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ? Latched : LevelSensitive,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouInt.ShareDisposition,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync AffMou, pDevExt->Cfg.fFloatSave);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = MouEnableTrans(pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = IoConnectInterrupt(&pDevExt->KbdIntObj, KbdIntHandler, pPortDevObj,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync &pDevExt->ShIntObj, IntVecKbd, IrqlKbd,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (KIRQL) ((IrqlCoord == (KIRQL)0) ? IrqlKbd : IrqlCoord),
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdInt.Flags == CM_RESOURCE_INTERRUPT_LATCHED
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ? Latched : LevelSensitive,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdInt.ShareDisposition,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync AffKbd, pDevExt->Cfg.fFloatSave);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KbdNameBase.Buffer, KbdNameFull.Buffer,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync REG_SZ,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync registryPath.Buffer, registryPath.Length);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouNameBase.Buffer, MouNameFull.Buffer,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync REG_SZ,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync registryPath.Buffer, registryPath.Length);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(status == STATUS_SUCCESS);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync int rcVBox = VbglInit();
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (RT_FAILURE(rcVBox))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Log(("VBoxMouseNT::DriverEntry: could not initialize guest library, rc = %Rrc\n", rcVBox));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* Continue working in non-VBox mode. */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VMMDevReqMouseStatus *pReq = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync rcVBox = VbglGRAlloc((VMMDevRequestHeader**)&pReq, sizeof(VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (RT_SUCCESS(rcVBox))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* Inform host that we support absolute */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pReq->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pReq->pointerXPos = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pReq->pointerYPos = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync rcVBox = VbglGRPerform(&pReq->header);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (RT_FAILURE(rcVBox))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Log(("VBoxMouseNT::DriverEntry: ERROR communicating new mouse capabilities to VMMDev. rc = %Rrc\n", rcVBox));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* We will use the allocated request buffer in the ServiceCallback to GET mouse status. */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pReq->header.requestType = VMMDevReq_GetMouseStatus;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->pReq = pReq;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync VbglTerminate();
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Log(("VBoxMouseNT::DriverEntry: could not allocate request buffer, rc = %Rrc\n", rcVBox));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* Continue working in non-VBox mode. */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDrvObj->DriverStartIo = I8042StartIo;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = I8042OpenClose;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = I8042OpenClose;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDrvObj->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = I8042Flush;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = I8042DevCtrl;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncfail:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (resources)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync resources->Count = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoReportResourceUsage(&resourceDeviceClass, pDrvObj, NULL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync 0, pPortDevObj, resources, resourceListSize, FALSE, &fConflict);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KbdIntObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoDisconnectInterrupt(pDevExt->KbdIntObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouIntObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoDisconnectInterrupt(pDevExt->MouIntObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->KbdExt.InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(pDevExt->KbdExt.InputData);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->MouExt.InputData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(pDevExt->MouExt.InputData);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->fUnmapRegs)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < pDevExt->Cfg.cPorts; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->DevRegs[i])
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MmUnmapIoSpace(pDevExt->DevRegs[i], pDevExt->Cfg.aPorts[i].u.Port.Length);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pPortDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (MouNameFull.Length > 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoDeleteSymbolicLink(&MouNameFull);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync IoDeleteDevice(pPortDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (resources)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(resources);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pInit)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(pInit);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (DevNameSuff.MaximumLength)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(DevNameSuff.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (KbdNameFull.MaximumLength)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(KbdNameFull.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (MouNameFull.MaximumLength)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(MouNameFull.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (resourceDeviceClass.MaximumLength)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(resourceDeviceClass.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (registryPath.MaximumLength)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(registryPath.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LogFlow(("VBoxMouseNT::DriverEntry: leave, status = %d\n", status));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID I8042Unload(PDRIVER_OBJECT pDrvObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NOREF(pDrvObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Build a resource list.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID CreateResList(PDEVEXT pDevExt, PCM_RESOURCE_LIST *pResList, PULONG pResListSize)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cPorts = pDevExt->Cfg.cPorts;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->Cfg.KbdInt.Type == CmResourceTypeInterrupt)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cPorts++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->Cfg.MouInt.Type == CmResourceTypeInterrupt)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync cPorts++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pResListSize = sizeof(CM_RESOURCE_LIST) + ((cPorts - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pResList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, *pResListSize);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!*pResList)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pResListSize = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(*pResList, *pResListSize);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->Count = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->List[0].InterfaceType = pDevExt->Cfg.InterfaceType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->List[0].BusNumber = pDevExt->Cfg.uBusNr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->List[0].PartialResourceList.Count = cPorts;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG i = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->Cfg.KbdInt.Type == CmResourceTypeInterrupt)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->List[0].PartialResourceList.PartialDescriptors[i++] = pDevExt->Cfg.KbdInt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->Cfg.MouInt.Type == CmResourceTypeInterrupt)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->List[0].PartialResourceList.PartialDescriptors[i++] = pDevExt->Cfg.MouInt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned j = 0; j < pDevExt->Cfg.cPorts; j++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (*pResList)->List[0].PartialResourceList.PartialDescriptors[i++] = pDevExt->Cfg.aPorts[j];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Read the i8042 controller command byte
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS GetCtrlCmd(ULONG HwDisEnMask, PDEVEXT pDevExt, PUCHAR pByte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (HwDisEnMask & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_DISABLE_KEYBOARD_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (HwDisEnMask & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_DISABLE_MOUSE_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (HwDisEnMask & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutBytePoll(i8042Cmd, FALSE/*=wait*/, NoDevice, pDevExt, I8042_ENABLE_KEYBOARD_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_READ_CONTROLLER_COMMAND_BYTE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned iRetry = 0; iRetry < 5; iRetry++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, pByte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status == STATUS_IO_TIMEOUT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(50);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (HwDisEnMask & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status2 = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_ENABLE_KEYBOARD_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status2))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = status2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (status == STATUS_SUCCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pByte &= (UCHAR)~CCB_DISABLE_KEYBOARD_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (HwDisEnMask & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status2 = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_ENABLE_MOUSE_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status2))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = status2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pByte &= (UCHAR)~CCB_DISABLE_MOUSE_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Write the i8042 controller command byte.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS PutCtrlCmd(PDEVEXT pDevExt, UCHAR Byte)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_WRITE_CONTROLLER_COMMAND_BYTE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return (PutBytePoll(i8042Dat, FALSE /*=wait*/, NoDevice, pDevExt, Byte));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Read the i8042 controller command byte.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID TransCtrlCmd(PDEVEXT pDevExt, PI8042TRANSMITCCBCTX pCtx)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR bCtrlCmd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCtx->Status = GetCtrlCmd(pCtx->HwDisEnMask, pDevExt, &bCtrlCmd);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(pCtx->Status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCtx->fAndOp)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync bCtrlCmd &= pCtx->ByteMask;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync bCtrlCmd |= pCtx->ByteMask;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCtx->Status = PutCtrlCmd(pDevExt, bCtrlCmd);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR bVrfyCmd;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCtx->Status = GetCtrlCmd(pCtx->HwDisEnMask, pDevExt, &bVrfyCmd);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( NT_SUCCESS(pCtx->Status)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && bVrfyCmd != bCtrlCmd)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCtx->Status = STATUS_DEVICE_DATA_ERROR;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Detect the number of mouse buttons.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouQueryButtons(PDEVICE_OBJECT pDevObj, PUCHAR pNumButtons)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, SET_MOUSE_RESOLUTION);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, 0x00);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < 3; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, SET_MOUSE_SCALING_1TO1);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, READ_MOUSE_STATUS);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR buttons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, &buttons);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (buttons == 2 || buttons == 3)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pNumButtons = buttons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *pNumButtons = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Initialize the i8042 mouse hardware.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouInitHw(PDEVICE_OBJECT pDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, MOUSE_RESET);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < 11200; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status) && byte == (UCHAR) MOUSE_COMPLETE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status != STATUS_IO_TIMEOUT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(50);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ((!NT_SUCCESS(status)) || (byte != MOUSE_ID_BYTE))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync MouFindWheel(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR numButtons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = MouQueryButtons(pDevObj, &numButtons);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (numButtons)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouAttr.NumberOfButtons = numButtons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, SET_MOUSE_SAMPLING_RATE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, 60);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, SET_MOUSE_RESOLUTION);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, (UCHAR)pDevExt->Cfg.MouseResolution);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncfail:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.uPrevSignAndOverflow = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseExpectingACK;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.LastByteReceived = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Initialize the i8042 keyboard hardware.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS KbdInitHw(PDEVICE_OBJECT pDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fWaitForAck = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT)pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncretry:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PutBytePoll(i8042Dat, fWaitForAck, KbdDevType, pDevExt, KEYBOARD_RESET);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER startOfSpin;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeQueryTickCount(&startOfSpin);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < 11200; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(KbdDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status == STATUS_IO_TIMEOUT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync LARGE_INTEGER nextQuery, difference, tenSeconds;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(50);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeQueryTickCount(&nextQuery);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync difference.QuadPart = nextQuery.QuadPart - startOfSpin.QuadPart;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync tenSeconds.QuadPart = 10*10*1000*1000;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(KeQueryTimeIncrement() <= MAXLONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (difference.QuadPart*KeQueryTimeIncrement() >= tenSeconds.QuadPart)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (fWaitForAck)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fWaitForAck = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto retry;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8042TRANSMITCCBCTX Ctx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.HwDisEnMask = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.fAndOp = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.ByteMask = (UCHAR) ~((UCHAR)CCB_KEYBOARD_TRANSLATE_MODE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync TransCtrlCmd(pDevExt, &Ctx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(Ctx.Status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync TransCtrlCmd(pDevExt, &Ctx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(Ctx.Status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = Ctx.Status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PKEYBOARD_ID pId = &pDevExt->Cfg.KbdAttr.KeyboardIdentifier;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, KbdDevType, pDevExt, SET_KEYBOARD_TYPEMATIC);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status == STATUS_SUCCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, KbdDevType, pDevExt,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ConvertTypematic(pDevExt->Cfg.KeyRepeatCurrent.Rate,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KeyRepeatCurrent.Delay));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* ignore errors */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, KbdDevType, pDevExt, SET_KEYBOARD_INDICATORS);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status == STATUS_SUCCESS)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, KbdDevType, pDevExt,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (UCHAR)pDevExt->Cfg.KbdInd.LedFlags);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* ignore errors */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->Cfg.KbdAttr.KeyboardMode == 1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.HwDisEnMask = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.fAndOp = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.ByteMask = CCB_KEYBOARD_TRANSLATE_MODE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync TransCtrlCmd(pDevExt, &Ctx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(Ctx.Status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (Ctx.Status == STATUS_DEVICE_DATA_ERROR)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (ENHANCED_KEYBOARD(*pId))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, KbdDevType, pDevExt, SELECT_SCAN_CODE_SET);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdAttr.KeyboardMode = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, KbdDevType, pDevExt, 1);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.KbdAttr.KeyboardMode = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = Ctx.Status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncfail:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.State = Idle;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.FirstByte = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->KbdExt.CurrentOutput.LastByte = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Initialize the i8042 controller, keyboard and mouse.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID InitHw(PDEVICE_OBJECT pDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUCHAR dataAddress = pDevExt->DevRegs[i8042Dat];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUCHAR commandAddress = pDevExt->DevRegs[i8042Cmd];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DrainOutBuf(dataAddress, commandAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync I8042TRANSMITCCBCTX Ctx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.HwDisEnMask = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.fAndOp = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.ByteMask = (UCHAR) ~((UCHAR)CCB_ENABLE_KEYBOARD_INTERRUPT | (UCHAR)CCB_ENABLE_MOUSE_INTERRUPT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync TransCtrlCmd(pDevExt, &Ctx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(Ctx.Status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DrainOutBuf(dataAddress, commandAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = MouInitHw(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = KbdInitHw(pDevObj);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_ENABLE_KEYBOARD_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DrainOutBuf(dataAddress, commandAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = PutBytePoll(i8042Cmd, FALSE /*=wait*/, NoDevice, pDevExt, I8042_ENABLE_MOUSE_DEVICE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DrainOutBuf(dataAddress, commandAddress);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pDevExt->HardwarePresent)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.HwDisEnMask = pDevExt->HardwarePresent;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.fAndOp = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.ByteMask = (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ? CCB_ENABLE_KEYBOARD_INTERRUPT : 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync Ctx.ByteMask |= (UCHAR)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT) ? CCB_ENABLE_MOUSE_INTERRUPT : 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync TransCtrlCmd(pDevExt, &Ctx);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(Ctx.Status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* ignore */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * retrieve the drivers service parameters from the registry
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic VOID HwGetRegstry(PINITEXT pInit, PUNICODE_STRING RegistryPath,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PUNICODE_STRING KeyboardDeviceName, PUNICODE_STRING PointerDeviceName)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PRTL_QUERY_REGISTRY_TABLE aQuery = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING parametersPath;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING defaultPointerName;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING defaultKeyboardName;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT defaultResendIterations = 3;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG iResend = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT defaultPollingIterations = 12000;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG pollingIterations = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT defaultPollingIterationsMaximum = 12000;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG pollingIterationsMaximum = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT defaultPollStatusIterations = 12000;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG pollStatusIterations = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG defaultDataQueueSize = 100;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG cButtons = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT cButtonsDef = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG sampleRate = 60;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT defaultSampleRate = 60;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG mouseResolution = 3;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT defaultMouseResolution = 3;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG overrideKeyboardType = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG invalidKeyboardType = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG overrideKeyboardSubtype = (ULONG)-1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG invalidKeyboardSubtype = (ULONG)-1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG defaultSynchPacket100ns = 10000000UL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG enableWheelDetection = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG defaultEnableWheelDetection = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PWSTR path = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync USHORT queries = 15;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PI8042CFGINF pCfg = &pInit->DevExt.Cfg;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->StallMicroseconds = 50;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync parametersPath.Buffer = NULL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync path = RegistryPath->Buffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery = (PRTL_QUERY_REGISTRY_TABLE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExAllocatePool(PagedPool, sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!aQuery)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(aQuery, sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&parametersPath, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync parametersPath.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync parametersPath.Buffer = (PWSTR)ExAllocatePool(PagedPool, parametersPath.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!parametersPath.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = STATUS_UNSUCCESSFUL;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlZeroMemory(parametersPath.Buffer, parametersPath.MaximumLength);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&parametersPath, path);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlAppendUnicodeToString(&parametersPath, L"\\Parameters");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&defaultKeyboardName, L"KeyboardPort");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlInitUnicodeString(&defaultPointerName, L"PointerPort");
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[0].Name = L"iResend";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[0].EntryContext = &iResend;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[0].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[0].DefaultData = &defaultResendIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[0].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[1].Name = L"PollingIterations";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[1].EntryContext = &pollingIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[1].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[1].DefaultData = &defaultPollingIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[1].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[2].Name = L"PollingIterationsMaximum";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[2].EntryContext = &pollingIterationsMaximum;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[2].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[2].DefaultData = &defaultPollingIterationsMaximum;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[2].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[3].Name = L"KeyboardDataQueueSize";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[3].EntryContext = &pCfg->KbdAttr.InputDataQueueLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[3].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[3].DefaultData = &defaultDataQueueSize;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[3].DefaultLength = sizeof(ULONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[4].Name = L"MouseDataQueueSize";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[4].EntryContext = &pCfg->MouAttr.InputDataQueueLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[4].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[4].DefaultData = &defaultDataQueueSize;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[4].DefaultLength = sizeof(ULONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[5].Name = L"NumberOfButtons";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[5].EntryContext = &cButtons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[5].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[5].DefaultData = &cButtonsDef;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[5].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[6].Name = L"SampleRate";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[6].EntryContext = &sampleRate;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[6].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[6].DefaultData = &defaultSampleRate;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[6].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[7].Name = L"MouseResolution";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[7].EntryContext = &mouseResolution;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[7].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[7].DefaultData = &defaultMouseResolution;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[7].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[8].Name = L"OverrideKeyboardType";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[8].EntryContext = &overrideKeyboardType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[8].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[8].DefaultData = &invalidKeyboardType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[8].DefaultLength = sizeof(ULONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[9].Name = L"OverrideKeyboardSubtype";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[9].EntryContext = &overrideKeyboardSubtype;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[9].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[9].DefaultData = &invalidKeyboardSubtype;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[9].DefaultLength = sizeof(ULONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[10].Name = L"KeyboardDeviceBaseName";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[10].EntryContext = KeyboardDeviceName;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[10].DefaultType = REG_SZ;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[10].DefaultData = defaultKeyboardName.Buffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[10].DefaultLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[11].Name = L"PointerDeviceBaseName";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[11].EntryContext = PointerDeviceName;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[11].DefaultType = REG_SZ;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[11].DefaultData = defaultPointerName.Buffer;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[11].DefaultLength = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[12].Name = L"MouseSynchIn100ns";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[12].EntryContext = &pInit->DevExt.MouExt.SynchTickCount;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[12].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[12].DefaultData = &defaultSynchPacket100ns;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[12].DefaultLength = sizeof(ULONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[13].Name = L"PollStatusIterations";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[13].EntryContext = &pollStatusIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[13].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[13].DefaultData = &defaultPollStatusIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[13].DefaultLength = sizeof(USHORT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[14].Flags = RTL_QUERY_REGISTRY_DIRECT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[14].Name = L"EnableWheelDetection";
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[14].EntryContext = &enableWheelDetection;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[14].DefaultType = REG_DWORD;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[14].DefaultData = &defaultEnableWheelDetection;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync aQuery[14].DefaultLength = sizeof(ULONG);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync parametersPath.Buffer, aQuery, NULL, NULL);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync /* driver defaults */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->iResend = defaultResendIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollingIterations = defaultPollingIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollingIterationsMaximum = defaultPollingIterationsMaximum;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollStatusIterations = defaultPollStatusIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.InputDataQueueLength = defaultDataQueueSize;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouAttr.InputDataQueueLength = defaultDataQueueSize;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->EnableWheelDetection = defaultEnableWheelDetection;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pInit->DevExt.MouExt.SynchTickCount = defaultSynchPacket100ns;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlCopyUnicodeString(KeyboardDeviceName, &defaultKeyboardName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlCopyUnicodeString(PointerDeviceName, &defaultPointerName);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->iResend = (USHORT)iResend;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollingIterations = (USHORT) pollingIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollingIterationsMaximum = (USHORT) pollingIterationsMaximum;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->PollStatusIterations = (USHORT) pollStatusIterations;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->EnableWheelDetection = (ULONG) ((enableWheelDetection) ? 1 : 0);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->KbdAttr.InputDataQueueLength == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.InputDataQueueLength = defaultDataQueueSize;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.InputDataQueueLength *= sizeof(KEYBOARD_INPUT_DATA);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->MouAttr.InputDataQueueLength == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouAttr.InputDataQueueLength = defaultDataQueueSize;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouAttr.InputDataQueueLength *= sizeof(MOUSE_INPUT_DATA);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouAttr.NumberOfButtons = (USHORT)cButtons;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouAttr.SampleRate = (USHORT)sampleRate;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouseResolution = (USHORT)mouseResolution;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (overrideKeyboardType != invalidKeyboardType)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (overrideKeyboardType <= RT_ELEMENTS(s_aKeybType))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Type = (UCHAR) overrideKeyboardType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (overrideKeyboardSubtype != invalidKeyboardSubtype)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Subtype = (UCHAR) overrideKeyboardSubtype;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pInit->DevExt.MouExt.SynchTickCount == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pInit->DevExt.MouExt.SynchTickCount = defaultSynchPacket100ns;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pInit->DevExt.MouExt.SynchTickCount /= KeQueryTimeIncrement();
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (parametersPath.Buffer)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(parametersPath.Buffer);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (aQuery)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ExFreePool(aQuery);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic void GetDevIdentifier(PKEY_VALUE_FULL_INFORMATION *ppInf, PUNICODE_STRING pStr)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pStr->Length = (USHORT)(*(ppInf + IoQueryDeviceIdentifier))->DataLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!pStr->Length)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pStr->MaximumLength = pStr->Length;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pStr->Buffer = (PWSTR) (((PUCHAR)(*(ppInf + IoQueryDeviceIdentifier)))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync + (*(ppInf + IoQueryDeviceIdentifier))->DataOffset);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic ULONG GetDevCfgData(PKEY_VALUE_FULL_INFORMATION *ppInf, PCM_PARTIAL_RESOURCE_LIST *ppData)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ULONG DataLength = (*(ppInf + IoQueryDeviceConfigurationData))->DataLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (DataLength)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync *ppData = (PCM_PARTIAL_RESOURCE_LIST)( ((PUCHAR) (*(ppInf + IoQueryDeviceConfigurationData)))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync + (*(ppInf + IoQueryDeviceConfigurationData))->DataOffset
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync + FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return DataLength;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Callout routine. Grab keyboard controller and peripheral configuration
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * information.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS KbdCallOut(PVOID pCtx, PUNICODE_STRING PathName,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE BusType, ULONG uBusNr, PKEY_VALUE_FULL_INFORMATION *pBusInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uCtrlType, ULONG uCtrlNr, PKEY_VALUE_FULL_INFORMATION *pCtrlInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uPrfType, ULONG uPrfNr, PKEY_VALUE_FULL_INFORMATION *pPrfInf)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING unicodeIdentifier;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GetDevIdentifier(pPrfInf, &unicodeIdentifier);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PINITEXT pInit = (PINITEXT)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = &pInit->DevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( (pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || !unicodeIdentifier.Length)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent |= KEYBOARD_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PI8042CFGINF pCfg = &pDevExt->Cfg;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Type = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Subtype = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_PARTIAL_RESOURCE_LIST pPrfData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (GetDevCfgData(pPrfInf, &pPrfData))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync unsigned cList = pPrfData->Count;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc = pPrfData->PartialDescriptors;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < cList; i++, pResDesc++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (pResDesc->Type)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case CmResourceTypeDeviceSpecific:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_KEYBOARD_DEVICE_DATA KbdData = (PCM_KEYBOARD_DEVICE_DATA)(((PUCHAR)pResDesc)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (KbdData->Type <= RT_ELEMENTS(s_aKeybType))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Type = KbdData->Type;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Subtype = KbdData->Subtype;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInd.LedFlags = (KbdData->KeyboardFlags >> 4) & 7;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->KbdAttr.KeyboardIdentifier.Type == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdAttr.KeyboardIdentifier.Type = 4;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInd.LedFlags = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->InterfaceType = BusType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->uBusNr = uBusNr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->fFloatSave = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fDefIntShare;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KINTERRUPT_MODE DefIntMode;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (BusType == MicroChannel)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fDefIntShare = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DefIntMode = LevelSensitive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fDefIntShare = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DefIntMode = Latched;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_PARTIAL_RESOURCE_LIST pCtrlData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (GetDevCfgData(pCtrlInf, &pCtrlData))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync unsigned cList = pCtrlData->Count;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc = pCtrlData->PartialDescriptors;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < cList; i++, pResDesc++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (pResDesc->Type)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case CmResourceTypePort:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ASSERT(pCfg->cPorts < i8042MaxPorts);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[pCfg->cPorts] = *pResDesc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[pCfg->cPorts].ShareDisposition = CmResourceShareDriverExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->cPorts++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case CmResourceTypeInterrupt:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt = *pResDesc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt.ShareDisposition = fDefIntShare ? CmResourceShareShared
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : CmResourceShareDeviceExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case CmResourceTypeDeviceSpecific:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!(pCfg->KbdInt.Type & CmResourceTypeInterrupt))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt.Type = CmResourceTypeInterrupt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt.ShareDisposition = fDefIntShare ? CmResourceShareShared
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : CmResourceShareDeviceExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt.Flags = (DefIntMode == Latched) ? CM_RESOURCE_INTERRUPT_LATCHED
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt.u.Interrupt.Level = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->KbdInt.u.Interrupt.Vector = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->cPorts == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].Type = CmResourceTypePort;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].Flags = CM_RESOURCE_PORT_IO;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].ShareDisposition = CmResourceShareDriverExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Start.LowPart = 0x60;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Start.HighPart = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Length = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].Type = CmResourceTypePort;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].Flags = CM_RESOURCE_PORT_IO;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].ShareDisposition = CmResourceShareDriverExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Start.LowPart = 0x64;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Start.HighPart = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Length = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->cPorts = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pCfg->cPorts == 1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Length = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd] = pCfg->aPorts[i8042Dat];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Start.LowPart += 4;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->cPorts++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->aPorts[i8042Cmd].u.Port.Start.LowPart < pCfg->aPorts[i8042Dat].u.Port.Start.LowPart)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CM_PARTIAL_RESOURCE_DESCRIPTOR Desc = pCfg->aPorts[i8042Dat];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat] = pCfg->aPorts[i8042Cmd];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd] = Desc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync/**
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * Callout routine. Grab the pointer controller and the peripheral
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync * configuration information.
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync */
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouCallOut(PVOID pCtx, PUNICODE_STRING PathName,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync INTERFACE_TYPE BusType, ULONG uBusNr, PKEY_VALUE_FULL_INFORMATION *pBusInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uCtrlType, ULONG uCtrlNr, PKEY_VALUE_FULL_INFORMATION *pCtrlInf,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CONFIGURATION_TYPE uPrfType, ULONG uPrfNr, PKEY_VALUE_FULL_INFORMATION *pPrfInf)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status = STATUS_SUCCESS;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UNICODE_STRING unicodeIdentifier;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GetDevIdentifier(pPrfInf, &unicodeIdentifier);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PINITEXT pInit = (PINITEXT)pCtx;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = &pInit->DevExt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( (pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync || unicodeIdentifier.Length == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync ANSI_STRING ansiString;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = RtlUnicodeStringToAnsiString(&ansiString, &unicodeIdentifier, TRUE);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (strstr(ansiString.Buffer, "PS2"))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent |= MOUSE_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync RtlFreeAnsiString(&ansiString);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!(pDevExt->HardwarePresent & MOUSE_HARDWARE_PRESENT))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PI8042CFGINF pCfg = &pDevExt->Cfg;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!(pDevExt->HardwarePresent & KEYBOARD_HARDWARE_PRESENT))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->InterfaceType = BusType;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->uBusNr = uBusNr;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->fFloatSave = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fDefIntShare;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KINTERRUPT_MODE DefIntMode;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->InterfaceType == MicroChannel)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fDefIntShare = TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DefIntMode = LevelSensitive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync fDefIntShare = FALSE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync DefIntMode = Latched;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_PARTIAL_RESOURCE_LIST pCtrlData;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (GetDevCfgData(pCtrlInf, &pCtrlData))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync unsigned cList = pCtrlData->Count;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc = pCtrlData->PartialDescriptors;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync BOOLEAN fPortInfoNeeded = pCfg->cPorts ? FALSE : TRUE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < cList; i++, pResDesc++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync switch (pResDesc->Type)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case CmResourceTypePort:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (fPortInfoNeeded)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[pCfg->cPorts] = *pResDesc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[pCfg->cPorts].ShareDisposition = CmResourceShareDriverExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->cPorts++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync case CmResourceTypeInterrupt:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt = *pResDesc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt.ShareDisposition = fDefIntShare ? CmResourceShareShared
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : CmResourceShareDeviceExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync default:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!(pCfg->MouInt.Type & CmResourceTypeInterrupt))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt.Type = CmResourceTypeInterrupt;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt.ShareDisposition = fDefIntShare ? CmResourceShareShared
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : CmResourceShareDeviceExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt.Flags = (DefIntMode == Latched) ? CM_RESOURCE_INTERRUPT_LATCHED
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync : CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt.u.Interrupt.Level = 12;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->MouInt.u.Interrupt.Vector = 12;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->cPorts == 0)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].Type = CmResourceTypePort;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].Flags = CM_RESOURCE_PORT_IO;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].ShareDisposition = CmResourceShareDriverExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Start.LowPart = 0x60;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Start.HighPart = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat].u.Port.Length = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].Type = CmResourceTypePort;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].Flags = CM_RESOURCE_PORT_IO;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].ShareDisposition = CmResourceShareDriverExclusive;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Start.LowPart = 0x64;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Start.HighPart = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Length = 1;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->cPorts = 2;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else if (pCfg->cPorts == 1)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd] = pCfg->aPorts[i8042Dat];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd].u.Port.Start.LowPart += 4;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->cPorts++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (pCfg->aPorts[i8042Cmd].u.Port.Start.LowPart < pCfg->aPorts[i8042Dat].u.Port.Start.LowPart)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync CM_PARTIAL_RESOURCE_DESCRIPTOR Desc = pCfg->aPorts[i8042Dat];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Dat] = pCfg->aPorts[i8042Cmd];
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pCfg->aPorts[i8042Cmd] = Desc;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic const UCHAR s_ucCommands[] =
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SET_MOUSE_SAMPLING_RATE, 200,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SET_MOUSE_SAMPLING_RATE, 100,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync SET_MOUSE_SAMPLING_RATE, 80,
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync GET_DEVICE_ID, 0
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync};
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncstatic NTSTATUS MouFindWheel(PDEVICE_OBJECT pDevObj)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync{
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync NTSTATUS status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync PDEVEXT pDevExt = (PDEVEXT) pDevObj->DeviceExtension;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!pDevExt->Cfg.EnableWheelDetection)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return STATUS_NO_SUCH_DEVICE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(50);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned iCmd = 0; s_ucCommands[iCmd];)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = PutBytePoll(i8042Dat, TRUE /*=wait*/, MouDevType, pDevExt, s_ucCommands[iCmd]);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (!NT_SUCCESS(status))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync goto fail;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync iCmd++;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(50);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync UCHAR byte;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync for (unsigned i = 0; i < 5; i++)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync status = GetBytePoll(CtrlDevType, pDevExt, &byte);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (status != STATUS_IO_TIMEOUT)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync break;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync KeStallExecutionProcessor(50);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if ( NT_SUCCESS(status)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync && (byte == MOUSE_ID_BYTE || byte == WHEELMOUSE_ID_BYTE))
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync if (byte == WHEELMOUSE_ID_BYTE)
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync {
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent |= (WHEELMOUSE_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT);
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->Cfg.MouAttr.MouseIdentifier = WHEELMOUSE_I8042_HARDWARE;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync else
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->HardwarePresent |= MOUSE_HARDWARE_PRESENT;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync }
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsyncfail:
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.uPrevSignAndOverflow = 0;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync pDevExt->MouExt.InputState = MouseExpectingACK;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync return status;
808a77f9219afa33641bb74dfff3d97948bb6b62vboxsync}