mirror of
https://github.com/reactos/reactos.git
synced 2025-07-11 08:04:14 +00:00
Change i8042prt to a PnP driver
Support power keys Support ctrl+scroll+scroll on debug builds Add support for driver filters Take care of more registry settings A lot of other changes svn path=/trunk/; revision=30000
This commit is contained in:
parent
8d1924094f
commit
e7e959fb0d
14 changed files with 4100 additions and 2922 deletions
|
@ -7,18 +7,28 @@ not based on the i8042prt example driver that's included with the DDK.
|
||||||
|
|
||||||
The directory contains these files:
|
The directory contains these files:
|
||||||
|
|
||||||
|
createclose.c: open/close devices functionnality
|
||||||
|
|
||||||
i8042prt.c: Main controller functionality, things shared by keyboards and mice
|
i8042prt.c: Main controller functionality, things shared by keyboards and mice
|
||||||
|
|
||||||
keyboard.c: keyboard functionality: detection, interrupt handling
|
keyboard.c: keyboard functionality: detection, interrupt handling
|
||||||
|
|
||||||
|
misc.c: misc things, mostly related to Irp passing
|
||||||
|
|
||||||
mouse.c: mouse functionality: detection, interrupt handling, packet parsing for
|
mouse.c: mouse functionality: detection, interrupt handling, packet parsing for
|
||||||
standard ps2 and microsoft mice
|
standard ps2 and microsoft mice
|
||||||
|
|
||||||
|
pnp.c: Plug&Play functionnality
|
||||||
|
|
||||||
ps2pp.c: logitech ps2++ mouse packat parsing (basic)
|
ps2pp.c: logitech ps2++ mouse packat parsing (basic)
|
||||||
|
|
||||||
|
readwrite.c: read/write to the i8042 controller
|
||||||
|
|
||||||
registry.c: registry reading
|
registry.c: registry reading
|
||||||
|
|
||||||
makefile, i8042prt.rc: obvious
|
setup.c: add keyboard support during the 1st stage setup
|
||||||
|
|
||||||
|
i8042prt.rc: obvious
|
||||||
|
|
||||||
|
|
||||||
Some parts of the driver make little sense. This is because it implements
|
Some parts of the driver make little sense. This is because it implements
|
||||||
|
@ -33,7 +43,6 @@ Things to add:
|
||||||
- General robustness: reset mouse if things go wrong
|
- General robustness: reset mouse if things go wrong
|
||||||
- Handling all registry settings
|
- Handling all registry settings
|
||||||
- ACPI
|
- ACPI
|
||||||
- Make it work more like a WDM driver
|
|
||||||
|
|
||||||
Things not to add:
|
Things not to add:
|
||||||
|
|
||||||
|
@ -49,18 +58,6 @@ Things requiring work elsewhere:
|
||||||
hardcoded cases, this should not be hard to fix.
|
hardcoded cases, this should not be hard to fix.
|
||||||
|
|
||||||
- Class drivers:
|
- Class drivers:
|
||||||
I wrote a keyboard class driver, which does keycode translations. It
|
|
||||||
should not do this, win32k should get untranslated keycodes and do
|
|
||||||
the translation itself.
|
|
||||||
|
|
||||||
I changed the mouse class driver (mouclass) to work like Microsofts mouclass.
|
|
||||||
Unfortunately this means that the original psaux driver doesn't work
|
|
||||||
anymore (the same holds for the other mice drivers, probably).
|
|
||||||
|
|
||||||
The keyboard class driver passes on ioctls from win32k, so it can change
|
|
||||||
keyboard settings. As far as I could see, the mouse class driver does not
|
|
||||||
do this yet.
|
|
||||||
|
|
||||||
The class drivers should be able to handle reads for more than one packet
|
The class drivers should be able to handle reads for more than one packet
|
||||||
at a time (kbdclass should, mouclass does not). Win32k should send such
|
at a time (kbdclass should, mouclass does not). Win32k should send such
|
||||||
requests.
|
requests.
|
||||||
|
|
52
reactos/drivers/input/i8042prt/createclose.c
Normal file
52
reactos/drivers/input/i8042prt/createclose.c
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/input/i8042prt/createclose.c
|
||||||
|
* PURPOSE: IRP_MJ_CREATE, IRP_MJ_CLEANUP and IRP_MJ_CLOSE operations
|
||||||
|
* PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
i8042Create(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MJ_CREATE\n");
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
i8042Cleanup(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MJ_CLEANUP\n");
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
i8042Close(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MJ_CLOSE\n");
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,39 +1,50 @@
|
||||||
#ifndef _I8042DRV_H
|
#ifndef _I8042PRT_H_
|
||||||
#define _I8042DRV_H
|
#define _I8042PRT_H_
|
||||||
|
|
||||||
#include <ntddk.h>
|
#include <ntifs.h>
|
||||||
#include <kbdmou.h>
|
#include <kbdmou.h>
|
||||||
#include <ntdd8042.h>
|
#include <ntdd8042.h>
|
||||||
|
#include <ntddkbd.h>
|
||||||
#ifdef _MSC_VER
|
#include <bugcodes.h>
|
||||||
#define STDCALL
|
#include <poclass.h>
|
||||||
#define DDKAPI
|
#include <kdfuncs.h>
|
||||||
#endif
|
#include <debug.h>
|
||||||
|
|
||||||
#define KEYBOARD_IRQ 1
|
|
||||||
#define MOUSE_IRQ 12
|
|
||||||
#define KBD_BUFFER_SIZE 32
|
|
||||||
|
|
||||||
#define WHEEL_DELTA 120
|
|
||||||
|
|
||||||
/*-----------------------------------------------------
|
/*-----------------------------------------------------
|
||||||
* DeviceExtension
|
* Structures
|
||||||
* --------------------------------------------------*/
|
* --------------------------------------------------*/
|
||||||
typedef struct _COMMAND_CONTEXT
|
|
||||||
|
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||||
|
#define I8042PRT_TAG TAG('8', '0', '4', '2')
|
||||||
|
|
||||||
|
typedef enum
|
||||||
{
|
{
|
||||||
int NumInput;
|
dsStopped,
|
||||||
int CurInput;
|
dsStarted,
|
||||||
UCHAR * Input;
|
dsPaused,
|
||||||
int NumOutput;
|
dsRemoved,
|
||||||
int CurOutput;
|
dsSurpriseRemoved
|
||||||
UCHAR * Output;
|
} DEVICE_STATE;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
BOOLEAN GotAck;
|
typedef struct _I8042_SETTINGS
|
||||||
KEVENT Event;
|
{
|
||||||
|
/* Registry settings */
|
||||||
PVOID DevExt;
|
ULONG KeyboardDataQueueSize; /* done */
|
||||||
} COMMAND_CONTEXT, *PCOMMAND_CONTEXT;
|
UNICODE_STRING KeyboardDeviceBaseName;
|
||||||
|
ULONG MouseDataQueueSize; /* done */
|
||||||
|
ULONG MouseResolution;
|
||||||
|
ULONG MouseSynchIn100ns;
|
||||||
|
ULONG NumberOfButtons;
|
||||||
|
UNICODE_STRING PointerDeviceBaseName;
|
||||||
|
ULONG PollStatusIterations; /* done */
|
||||||
|
ULONG OverrideKeyboardType;
|
||||||
|
ULONG OverrideKeyboardSubtype;
|
||||||
|
ULONG PollingIterations; /* done */
|
||||||
|
ULONG PollingIterationsMaximum;
|
||||||
|
ULONG ResendIterations; /* done */
|
||||||
|
ULONG SampleRate;
|
||||||
|
ULONG CrashOnCtrlScroll; /* done */
|
||||||
|
} I8042_SETTINGS, *PI8042_SETTINGS;
|
||||||
|
|
||||||
typedef enum _MOUSE_TIMEOUT_STATE
|
typedef enum _MOUSE_TIMEOUT_STATE
|
||||||
{
|
{
|
||||||
|
@ -42,108 +53,47 @@ typedef enum _MOUSE_TIMEOUT_STATE
|
||||||
TimeoutCancel
|
TimeoutCancel
|
||||||
} MOUSE_TIMEOUT_STATE, *PMOUSE_TIMEOUT_STATE;
|
} MOUSE_TIMEOUT_STATE, *PMOUSE_TIMEOUT_STATE;
|
||||||
|
|
||||||
/* TODO: part of this should be in the _ATTRIBUTES structs instead */
|
typedef struct _INTERRUPT_DATA
|
||||||
typedef struct _I8042_SETTINGS
|
|
||||||
{
|
{
|
||||||
ULONG Headless; /* done */
|
PKINTERRUPT Object;
|
||||||
ULONG CrashScroll;
|
ULONG Vector;
|
||||||
ULONG CrashSysRq; /* done */
|
KIRQL Dirql;
|
||||||
ULONG ReportResetErrors;
|
KINTERRUPT_MODE InterruptMode;
|
||||||
ULONG PollStatusIterations; /* done */
|
BOOLEAN ShareInterrupt;
|
||||||
ULONG ResendIterations; /* done */
|
KAFFINITY Affinity;
|
||||||
ULONG PollingIterations;
|
} INTERRUPT_DATA, *PINTERRUPT_DATA;
|
||||||
ULONG PollingIterationsMaximum;
|
|
||||||
ULONG OverrideKeyboardType;
|
|
||||||
ULONG OverrideKeyboardSubtype;
|
|
||||||
ULONG MouseResendStallTime;
|
|
||||||
ULONG MouseSynchIn100ns; /* done */
|
|
||||||
ULONG MouseResolution; /* done */
|
|
||||||
ULONG NumberOfButtons;
|
|
||||||
ULONG EnableWheelDetection;
|
|
||||||
} I8042_SETTINGS, *PI8042_SETTINGS;
|
|
||||||
|
|
||||||
typedef enum _I8042_MOUSE_TYPE
|
#define WHEEL_DELTA 120
|
||||||
|
|
||||||
|
struct _I8042_KEYBOARD_EXTENSION;
|
||||||
|
typedef struct _I8042_KEYBOARD_EXTENSION *PI8042_KEYBOARD_EXTENSION;
|
||||||
|
struct _I8042_MOUSE_EXTENSION;
|
||||||
|
typedef struct _I8042_MOUSE_EXTENSION *PI8042_MOUSE_EXTENSION;
|
||||||
|
|
||||||
|
/* PORT_DEVICE_EXTENSION.Flags */
|
||||||
|
#define KEYBOARD_PRESENT 0x01 /* A keyboard is attached */
|
||||||
|
#define KEYBOARD_CONNECTED 0x02 /* Keyboard received IOCTL_INTERNAL_KEYBOARD_CONNECT */
|
||||||
|
#define KEYBOARD_STARTED 0x04 /* Keyboard FDO received IRP_MN_START_DEVICE */
|
||||||
|
#define KEYBOARD_INITIALIZED 0x08 /* Keyboard interrupt is connected */
|
||||||
|
#define MOUSE_PRESENT 0x10 /* A mouse is attached */
|
||||||
|
#define MOUSE_CONNECTED 0x20 /* Mouse received IOCTL_INTERNAL_MOUSE_CONNECT */
|
||||||
|
#define MOUSE_STARTED 0x40 /* Mouse FDO received IRP_MN_START_DEVICE */
|
||||||
|
#define MOUSE_INITIALIZED 0x80 /* Mouse interrupt is connected */
|
||||||
|
|
||||||
|
typedef struct _PORT_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
GenericPS2,
|
PUCHAR DataPort; /* Usually 0x60 */
|
||||||
Intellimouse,
|
PUCHAR ControlPort; /* Usually 0x64 */
|
||||||
IntellimouseExplorer,
|
I8042_SETTINGS Settings;
|
||||||
Ps2pp
|
ULONG Flags;
|
||||||
} I8042_MOUSE_TYPE, *PI8042_MOUSE_TYPE;
|
|
||||||
|
|
||||||
typedef enum _I8042_DEVICE_TYPE
|
PI8042_KEYBOARD_EXTENSION KeyboardExtension;
|
||||||
{
|
INTERRUPT_DATA KeyboardInterrupt;
|
||||||
Keyboard,
|
PI8042_MOUSE_EXTENSION MouseExtension;
|
||||||
Mouse
|
INTERRUPT_DATA MouseInterrupt;
|
||||||
} I8042_DEVICE_TYPE, *PI8042_DEVICE_TYPE;
|
|
||||||
|
|
||||||
typedef struct _I8042_DEVICE
|
|
||||||
{
|
|
||||||
LIST_ENTRY ListEntry;
|
|
||||||
PDEVICE_OBJECT Pdo;
|
|
||||||
} I8042_DEVICE, *PI8042_DEVICE;
|
|
||||||
|
|
||||||
typedef struct _DEVICE_EXTENSION
|
|
||||||
{
|
|
||||||
PDEVICE_OBJECT KeyboardObject;
|
|
||||||
PDEVICE_OBJECT MouseObject;
|
|
||||||
|
|
||||||
CONNECT_DATA KeyboardData;
|
|
||||||
CONNECT_DATA MouseData;
|
|
||||||
|
|
||||||
BOOLEAN KeyboardExists;
|
|
||||||
BOOLEAN KeyboardIsAT;
|
|
||||||
BOOLEAN MouseExists;
|
|
||||||
|
|
||||||
BOOLEAN KeyboardClaimed;
|
|
||||||
BOOLEAN MouseClaimed;
|
|
||||||
|
|
||||||
ULONG BusNumber;
|
|
||||||
LIST_ENTRY BusDevices;
|
|
||||||
|
|
||||||
INTERNAL_I8042_START_INFORMATION KeyboardStartInformation;
|
|
||||||
INTERNAL_I8042_START_INFORMATION MouseStartInformation;
|
|
||||||
|
|
||||||
INTERNAL_I8042_HOOK_KEYBOARD KeyboardHook;
|
|
||||||
INTERNAL_I8042_HOOK_MOUSE MouseHook;
|
|
||||||
|
|
||||||
PKINTERRUPT KeyboardInterruptObject;
|
|
||||||
PKINTERRUPT MouseInterruptObject;
|
|
||||||
PKINTERRUPT HighestDIRQLInterrupt;
|
PKINTERRUPT HighestDIRQLInterrupt;
|
||||||
KSPIN_LOCK SpinLock;
|
KSPIN_LOCK SpinLock;
|
||||||
KDPC DpcKbd;
|
KIRQL HighestDirql;
|
||||||
KDPC DpcMouse;
|
|
||||||
|
|
||||||
KTIMER TimerMouseTimeout;
|
|
||||||
KDPC DpcMouseTimeout;
|
|
||||||
MOUSE_TIMEOUT_STATE MouseTimeoutState;
|
|
||||||
BOOLEAN MouseTimeoutActive;
|
|
||||||
|
|
||||||
KEYBOARD_ATTRIBUTES KeyboardAttributes;
|
|
||||||
KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicators;
|
|
||||||
KEYBOARD_TYPEMATIC_PARAMETERS KeyboardTypematic;
|
|
||||||
|
|
||||||
BOOLEAN WantAck;
|
|
||||||
BOOLEAN WantOutput;
|
|
||||||
BOOLEAN SignalEvent;
|
|
||||||
|
|
||||||
KEYBOARD_SCAN_STATE KeyboardScanState;
|
|
||||||
BOOLEAN KeyComplete;
|
|
||||||
KEYBOARD_INPUT_DATA *KeyboardBuffer;
|
|
||||||
ULONG KeysInBuffer;
|
|
||||||
|
|
||||||
MOUSE_ATTRIBUTES MouseAttributes;
|
|
||||||
|
|
||||||
MOUSE_STATE MouseState;
|
|
||||||
BOOLEAN MouseComplete;
|
|
||||||
MOUSE_RESET_SUBSTATE MouseResetState;
|
|
||||||
MOUSE_INPUT_DATA *MouseBuffer;
|
|
||||||
ULONG MouseInBuffer;
|
|
||||||
USHORT MouseButtonState;
|
|
||||||
ULARGE_INTEGER MousePacketStartTime;
|
|
||||||
|
|
||||||
UCHAR MouseLogiBuffer[3];
|
|
||||||
UCHAR MouseLogitechID;
|
|
||||||
I8042_MOUSE_TYPE MouseType;
|
|
||||||
|
|
||||||
OUTPUT_PACKET Packet;
|
OUTPUT_PACKET Packet;
|
||||||
ULONG PacketResends;
|
ULONG PacketResends;
|
||||||
|
@ -154,228 +104,351 @@ typedef struct _DEVICE_EXTENSION
|
||||||
|
|
||||||
PIRP CurrentIrp;
|
PIRP CurrentIrp;
|
||||||
PDEVICE_OBJECT CurrentIrpDevice;
|
PDEVICE_OBJECT CurrentIrpDevice;
|
||||||
|
} PORT_DEVICE_EXTENSION, *PPORT_DEVICE_EXTENSION;
|
||||||
|
|
||||||
/* registry config values */
|
typedef struct _I8042_DRIVER_EXTENSION
|
||||||
I8042_SETTINGS Settings;
|
{
|
||||||
|
UNICODE_STRING RegistryPath;
|
||||||
|
|
||||||
/* Debugger stuff */
|
PORT_DEVICE_EXTENSION Port;
|
||||||
BOOLEAN TabPressed;
|
LIST_ENTRY DeviceListHead;
|
||||||
ULONG DebugKey;
|
KSPIN_LOCK DeviceListLock;
|
||||||
PIO_WORKITEM DebugWorkItem;
|
} I8042_DRIVER_EXTENSION, *PI8042_DRIVER_EXTENSION;
|
||||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
|
||||||
|
typedef enum _I8042_DEVICE_TYPE
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Keyboard,
|
||||||
|
Mouse,
|
||||||
|
PhysicalDeviceObject
|
||||||
|
} I8042_DEVICE_TYPE, *PI8042_DEVICE_TYPE;
|
||||||
|
|
||||||
typedef struct _FDO_DEVICE_EXTENSION
|
typedef struct _FDO_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION PortDevExt;
|
|
||||||
I8042_DEVICE_TYPE Type;
|
I8042_DEVICE_TYPE Type;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
// Linkage in I8042_DRIVER_EXTENSION.DeviceListHead
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
// Associated device object (FDO)
|
||||||
|
PDEVICE_OBJECT Fdo;
|
||||||
|
// Associated device object (PDO)
|
||||||
|
PDEVICE_OBJECT Pdo;
|
||||||
|
// Lower device object
|
||||||
|
PDEVICE_OBJECT LowerDevice;
|
||||||
|
// Current state of the driver
|
||||||
|
DEVICE_STATE PnpState;
|
||||||
|
|
||||||
LIST_ENTRY BusDevices;
|
PPORT_DEVICE_EXTENSION PortDeviceExtension;
|
||||||
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct _I8042_KEYBOARD_EXTENSION
|
||||||
|
{
|
||||||
|
FDO_DEVICE_EXTENSION Common;
|
||||||
|
CONNECT_DATA KeyboardData;
|
||||||
|
INTERNAL_I8042_HOOK_KEYBOARD KeyboardHook; /* FIXME: IsrWritePort ignored */
|
||||||
|
KDPC DpcKeyboard;
|
||||||
|
|
||||||
|
KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicators;
|
||||||
|
|
||||||
|
KEYBOARD_SCAN_STATE KeyboardScanState;
|
||||||
|
BOOLEAN KeyComplete;
|
||||||
|
PKEYBOARD_INPUT_DATA KeyboardBuffer;
|
||||||
|
ULONG KeysInBuffer;
|
||||||
|
|
||||||
|
/* Power keys items */
|
||||||
|
ULONG ReportedCaps;
|
||||||
|
ULONG NewCaps;
|
||||||
|
ULONG LastPowerKey;
|
||||||
|
UNICODE_STRING PowerInterfaceName;
|
||||||
|
PIO_WORKITEM PowerWorkItem;
|
||||||
|
PIRP PowerIrp;
|
||||||
|
|
||||||
|
/* Debug items */
|
||||||
|
ULONG ComboPosition;
|
||||||
|
PIO_WORKITEM DebugWorkItem;
|
||||||
|
BOOLEAN TabPressed;
|
||||||
|
} I8042_KEYBOARD_EXTENSION;
|
||||||
|
|
||||||
|
typedef enum _I8042_MOUSE_TYPE
|
||||||
|
{
|
||||||
|
GenericPS2,
|
||||||
|
Intellimouse,
|
||||||
|
IntellimouseExplorer,
|
||||||
|
Ps2pp
|
||||||
|
} I8042_MOUSE_TYPE, *PI8042_MOUSE_TYPE;
|
||||||
|
|
||||||
|
typedef struct _I8042_MOUSE_EXTENSION
|
||||||
|
{
|
||||||
|
FDO_DEVICE_EXTENSION Common;
|
||||||
|
CONNECT_DATA MouseData;
|
||||||
|
INTERNAL_I8042_HOOK_MOUSE MouseHook;
|
||||||
|
KDPC DpcMouse;
|
||||||
|
|
||||||
|
MOUSE_ATTRIBUTES MouseAttributes;
|
||||||
|
|
||||||
|
MOUSE_STATE MouseState;
|
||||||
|
BOOLEAN MouseComplete;
|
||||||
|
MOUSE_RESET_SUBSTATE MouseResetState;
|
||||||
|
PMOUSE_INPUT_DATA MouseBuffer;
|
||||||
|
ULONG MouseInBuffer;
|
||||||
|
USHORT MouseButtonState;
|
||||||
|
ULARGE_INTEGER MousePacketStartTime;
|
||||||
|
|
||||||
|
KTIMER TimerMouseTimeout;
|
||||||
|
KDPC DpcMouseTimeout;
|
||||||
|
MOUSE_TIMEOUT_STATE MouseTimeoutState;
|
||||||
|
BOOLEAN MouseTimeoutActive;
|
||||||
|
|
||||||
|
UCHAR MouseLogiBuffer[3];
|
||||||
|
I8042_MOUSE_TYPE MouseType;
|
||||||
|
} I8042_MOUSE_EXTENSION;
|
||||||
|
|
||||||
typedef struct _I8042_HOOK_WORKITEM
|
typedef struct _I8042_HOOK_WORKITEM
|
||||||
{
|
{
|
||||||
PIO_WORKITEM WorkItem;
|
PIO_WORKITEM WorkItem;
|
||||||
PDEVICE_OBJECT Target;
|
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
} I8042_HOOK_WORKITEM, *PI8042_HOOK_WORKITEM;
|
} I8042_HOOK_WORKITEM, *PI8042_HOOK_WORKITEM;
|
||||||
|
|
||||||
/*
|
/*-----------------------------------------------------
|
||||||
* Some defines
|
* Some defines
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
|
||||||
#define TAG_I8042 TAG('8', '0', '4', '2')
|
|
||||||
|
|
||||||
#define KBD_WRAP_MASK 0x1F
|
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
|
||||||
|
|
||||||
#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
|
#define KEYBOARD_POWER_CODE 0x5E
|
||||||
#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
|
#define KEYBOARD_SLEEP_CODE 0x5F
|
||||||
|
#define KEYBOARD_WAKE_CODE 0x63
|
||||||
|
|
||||||
|
/*-----------------------------------------------------
|
||||||
/*
|
|
||||||
* Keyboard controller ports
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define I8042_DATA_PORT ((PUCHAR)0x60)
|
|
||||||
#define I8042_CTRL_PORT ((PUCHAR)0x64)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Controller commands
|
* Controller commands
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
#define KBD_READ_MODE 0x20
|
#define KBD_READ_MODE 0x20
|
||||||
#define KBD_WRITE_MODE 0x60
|
#define KBD_WRITE_MODE 0x60
|
||||||
#define KBD_SELF_TEST 0xAA
|
|
||||||
#define KBD_LINE_TEST 0xAB
|
#define KBD_LINE_TEST 0xAB
|
||||||
#define KBD_CTRL_ENABLE 0xAE
|
|
||||||
|
|
||||||
#define MOUSE_LINE_TEST 0xA9
|
#define MOUSE_LINE_TEST 0xA9
|
||||||
#define MOUSE_CTRL_ENABLE 0xA8
|
#define CTRL_SELF_TEST 0xAA
|
||||||
|
#define CTRL_WRITE_MOUSE 0xD4
|
||||||
|
|
||||||
#define KBD_READ_OUTPUT_PORT 0xD0
|
/*-----------------------------------------------------
|
||||||
#define KBD_WRITE_OUTPUT_PORT 0xD1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keyboard commands
|
* Keyboard commands
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
#define KBD_SET_LEDS 0xED
|
#define KBD_CMD_SET_LEDS 0xED
|
||||||
#define KBD_GET_ID 0xF2
|
#define KBD_CMD_GET_ID 0xF2
|
||||||
#define KBD_ENABLE 0xF4
|
|
||||||
#define KBD_DISABLE 0xF5
|
|
||||||
#define KBD_RESET 0xFF
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------
|
||||||
|
* Keyboard responses
|
||||||
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Keyboard responces
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define KBD_BATCC 0xAA
|
|
||||||
#define KBD_ACK 0xFA
|
#define KBD_ACK 0xFA
|
||||||
#define KBD_NACK 0xFC
|
#define KBD_NACK 0xFC
|
||||||
#define KBD_RESEND 0xFE
|
#define KBD_RESEND 0xFE
|
||||||
|
|
||||||
/*
|
/*-----------------------------------------------------
|
||||||
* Controller status register bits
|
* Controller status register bits
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
#define KBD_OBF 0x01
|
#define KBD_OBF 0x01
|
||||||
#define KBD_IBF 0x02
|
#define KBD_IBF 0x02
|
||||||
#define KBD_AUX 0x10
|
#define MOU_OBF 0x20
|
||||||
#define KBD_GTO 0x40
|
|
||||||
#define KBD_PERR 0x80
|
#define KBD_PERR 0x80
|
||||||
|
|
||||||
/*
|
/*-----------------------------------------------------
|
||||||
* Controller command byte bits
|
* Controller command byte bits
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
#define CCB_KBD_INT_ENAB 0x01
|
#define CCB_KBD_INT_ENAB 0x01
|
||||||
#define CCB_MOUSE_INT_ENAB 0x02
|
#define CCB_MOUSE_INT_ENAB 0x02
|
||||||
#define CCB_SYSTEM_FLAG 0x04
|
#define CCB_SYSTEM_FLAG 0x04
|
||||||
#define CCB_IGN_KEY_LOCK 0x08
|
|
||||||
#define CCB_KBD_DISAB 0x10
|
#define CCB_KBD_DISAB 0x10
|
||||||
#define CCB_MOUSE_DISAB 0x20
|
#define CCB_MOUSE_DISAB 0x20
|
||||||
#define CCB_TRANSLATE 0x40
|
#define CCB_TRANSLATE 0x40
|
||||||
|
|
||||||
|
/*-----------------------------------------------------
|
||||||
/*
|
|
||||||
* LED bits
|
* LED bits
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
#define KBD_LED_SCROLL 0x01
|
#define KBD_LED_SCROLL 0x01
|
||||||
#define KBD_LED_NUM 0x02
|
#define KBD_LED_NUM 0x02
|
||||||
#define KBD_LED_CAPS 0x04
|
#define KBD_LED_CAPS 0x04
|
||||||
|
|
||||||
/*
|
/*-----------------------------------------------------
|
||||||
|
* Mouse commands
|
||||||
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MOU_CMD_GET_ID 0xF2
|
||||||
|
#define MOU_CMD_RESET 0xFF
|
||||||
|
|
||||||
|
/*-----------------------------------------------------
|
||||||
* Mouse responses
|
* Mouse responses
|
||||||
*/
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
#define MOUSE_ACK 0xFA
|
#define MOUSE_ACK 0xFA
|
||||||
#define MOUSE_ERROR 0xFC
|
#define MOUSE_ERROR 0xFC
|
||||||
#define MOUSE_NACK 0xFE
|
#define MOUSE_NACK 0xFE
|
||||||
|
|
||||||
/* i8042prt.c */
|
/*-----------------------------------------------------
|
||||||
extern UNICODE_STRING I8042RegistryPath;
|
* Prototypes
|
||||||
|
* --------------------------------------------------*/
|
||||||
|
|
||||||
NTSTATUS I8042ReadData(UCHAR *Data);
|
/* createclose.c */
|
||||||
|
|
||||||
NTSTATUS I8042ReadStatus(UCHAR *Status);
|
IO_WORKITEM_ROUTINE i8042SendHookWorkItem;
|
||||||
|
|
||||||
NTSTATUS I8042ReadDataWait(PDEVICE_EXTENSION DevExt, UCHAR *Data);
|
DRIVER_DISPATCH i8042Create;
|
||||||
|
|
||||||
VOID I8042Flush();
|
DRIVER_DISPATCH i8042Cleanup;
|
||||||
|
|
||||||
VOID STDCALL I8042IsrWritePort(PDEVICE_EXTENSION DevExt,
|
DRIVER_DISPATCH i8042Close;
|
||||||
UCHAR Value,
|
|
||||||
UCHAR SelectCmd);
|
|
||||||
|
|
||||||
NTSTATUS STDCALL I8042SynchWritePort(PDEVICE_EXTENSION DevExt,
|
|
||||||
UCHAR Port,
|
|
||||||
UCHAR Value,
|
|
||||||
BOOLEAN WaitForAck);
|
|
||||||
|
|
||||||
NTSTATUS STDCALL I8042StartPacket(PDEVICE_EXTENSION DevExt,
|
|
||||||
PDEVICE_OBJECT Device,
|
|
||||||
PUCHAR Bytes,
|
|
||||||
ULONG ByteCount,
|
|
||||||
PIRP Irp);
|
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042PacketIsr(PDEVICE_EXTENSION DevExt,
|
|
||||||
UCHAR Output);
|
|
||||||
|
|
||||||
VOID I8042PacketDpc(PDEVICE_EXTENSION DevExt);
|
|
||||||
|
|
||||||
IO_WORKITEM_ROUTINE I8042SendHookWorkItem;
|
|
||||||
VOID STDCALL I8042SendHookWorkItem(PDEVICE_OBJECT DeviceObject,
|
|
||||||
PVOID Context);
|
|
||||||
|
|
||||||
BOOLEAN I8042Write(PDEVICE_EXTENSION DevExt, PUCHAR addr, UCHAR data);
|
|
||||||
|
|
||||||
NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
|
|
||||||
PUNICODE_STRING RegistryPath);
|
|
||||||
|
|
||||||
/* keyboard.c */
|
/* keyboard.c */
|
||||||
VOID STDCALL I8042IsrWritePortKbd(PVOID Context,
|
|
||||||
UCHAR Value);
|
|
||||||
|
|
||||||
NTSTATUS STDCALL I8042SynchWritePortKbd(PVOID Context,
|
NTSTATUS DDKAPI
|
||||||
UCHAR Value,
|
i8042SynchWritePortKbd(
|
||||||
BOOLEAN WaitForAck);
|
IN PVOID Context,
|
||||||
|
IN UCHAR Value,
|
||||||
|
IN BOOLEAN WaitForAck);
|
||||||
|
|
||||||
KSERVICE_ROUTINE I8042InterruptServiceKbd;
|
DRIVER_STARTIO i8042KbdStartIo;
|
||||||
BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt,
|
|
||||||
VOID * Context);
|
|
||||||
|
|
||||||
VOID STDCALL I8042DpcRoutineKbd(PKDPC Dpc,
|
DRIVER_DISPATCH i8042KbdDeviceControl;
|
||||||
PVOID DeferredContext,
|
|
||||||
PVOID SystemArgument1,
|
|
||||||
PVOID SystemArgument2);
|
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042StartIoKbd(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
DRIVER_DISPATCH i8042KbdInternalDeviceControl;
|
||||||
|
|
||||||
NTSTATUS STDCALL I8042InternalDeviceControlKbd(PDEVICE_OBJECT DeviceObject,
|
KSERVICE_ROUTINE i8042KbdInterruptService;
|
||||||
PIRP Irp);
|
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042KeyboardEnable(PDEVICE_EXTENSION DevExt);
|
/* i8042prt.c */
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042KeyboardEnableInterrupt(PDEVICE_EXTENSION DevExt);
|
DRIVER_ADD_DEVICE i8042AddDevice;
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042DetectKeyboard(PDEVICE_EXTENSION DevExt);
|
BOOLEAN
|
||||||
|
i8042PacketIsr(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Output);
|
||||||
|
|
||||||
/* registry.c */
|
NTSTATUS
|
||||||
VOID STDCALL I8042ReadRegistry(PDRIVER_OBJECT DriverObject,
|
i8042StartPacket(
|
||||||
PDEVICE_EXTENSION DevExt);
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PFDO_DEVICE_EXTENSION FdoDeviceExtension,
|
||||||
|
IN PUCHAR Bytes,
|
||||||
|
IN ULONG ByteCount,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
||||||
|
/* misc.c */
|
||||||
|
|
||||||
|
DRIVER_DISPATCH ForwardIrpAndForget;
|
||||||
|
|
||||||
|
DRIVER_DISPATCH ForwardIrpAndWait;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DuplicateUnicodeString(
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN PCUNICODE_STRING SourceString,
|
||||||
|
OUT PUNICODE_STRING DestinationString);
|
||||||
|
|
||||||
/* mouse.c */
|
/* mouse.c */
|
||||||
VOID STDCALL I8042DpcRoutineMouse(PKDPC Dpc,
|
|
||||||
PVOID DeferredContext,
|
|
||||||
PVOID SystemArgument1,
|
|
||||||
PVOID SystemArgument2);
|
|
||||||
|
|
||||||
VOID STDCALL I8042DpcRoutineMouseTimeout(PKDPC Dpc,
|
VOID
|
||||||
PVOID DeferredContext,
|
i8042MouHandle(
|
||||||
PVOID SystemArgument1,
|
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||||
PVOID SystemArgument2);
|
IN UCHAR Output);
|
||||||
|
|
||||||
KSERVICE_ROUTINE I8042InterruptServiceMouse;
|
VOID
|
||||||
BOOLEAN STDCALL I8042InterruptServiceMouse(struct _KINTERRUPT *Interrupt,
|
i8042MouHandleButtons(
|
||||||
VOID *Context);
|
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||||
|
IN USHORT Mask);
|
||||||
|
|
||||||
NTSTATUS STDCALL I8042InternalDeviceControlMouse(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS
|
||||||
PIRP Irp);
|
i8042MouInitialize(
|
||||||
|
IN PI8042_MOUSE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
VOID STDCALL I8042QueueMousePacket(PVOID Context);
|
DRIVER_DISPATCH i8042MouInternalDeviceControl;
|
||||||
|
|
||||||
VOID STDCALL I8042MouseHandleButtons(PDEVICE_EXTENSION DevExt,
|
KSERVICE_ROUTINE i8042MouInterruptService;
|
||||||
USHORT Mask);
|
|
||||||
|
|
||||||
VOID STDCALL I8042MouseHandle(PDEVICE_EXTENSION DevExt,
|
/* pnp.c */
|
||||||
UCHAR Output);
|
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt);
|
BOOLEAN
|
||||||
BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt);
|
i8042ChangeMode(
|
||||||
BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt);
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR FlagsToDisable,
|
||||||
|
IN UCHAR FlagsToEnable);
|
||||||
|
|
||||||
|
DRIVER_DISPATCH i8042Pnp;
|
||||||
|
|
||||||
/* ps2pp.c */
|
/* ps2pp.c */
|
||||||
VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input);
|
VOID
|
||||||
|
i8042MouHandlePs2pp(
|
||||||
|
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Input);
|
||||||
|
|
||||||
#endif // _KEYBOARD_H_
|
/* readwrite.c */
|
||||||
|
|
||||||
|
VOID
|
||||||
|
i8042Flush(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
i8042IsrWritePort(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Value,
|
||||||
|
IN UCHAR SelectCmd OPTIONAL);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
i8042ReadData(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR StatusFlags,
|
||||||
|
OUT PUCHAR Data);
|
||||||
|
#define i8042ReadKeyboardData(DeviceExtension, Data) \
|
||||||
|
i8042ReadData(DeviceExtension, KBD_OBF, Data)
|
||||||
|
#define i8042ReadMouseData(DeviceExtension, Data) \
|
||||||
|
i8042ReadData(DeviceExtension, MOU_OBF, Data)
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
i8042ReadDataWait(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
OUT PUCHAR Data);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
i8042ReadStatus(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
OUT PUCHAR Status);
|
||||||
|
|
||||||
|
NTSTATUS DDKAPI
|
||||||
|
i8042SynchReadPort(
|
||||||
|
IN PVOID Context,
|
||||||
|
OUT PUCHAR Value,
|
||||||
|
IN BOOLEAN WaitForAck);
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
i8042SynchWritePort(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Port,
|
||||||
|
IN UCHAR Value,
|
||||||
|
IN BOOLEAN WaitForAck);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
i8042Write(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PUCHAR addr,
|
||||||
|
IN UCHAR data);
|
||||||
|
|
||||||
|
/* registry.c */
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ReadRegistryEntries(
|
||||||
|
IN PUNICODE_STRING RegistryPath,
|
||||||
|
OUT PI8042_SETTINGS Settings);
|
||||||
|
|
||||||
|
/* setup.c */
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
IsFirstStageSetup(
|
||||||
|
VOID);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
i8042AddLegacyKeyboard(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath);
|
||||||
|
|
||||||
|
#endif // _I8042PRT_H_
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||||
<module name="i8042prt" type="kernelmodedriver" installbase="system32/drivers" installname="i8042prt.sys">
|
<module name="i8042prt" type="kernelmodedriver" installbase="system32/drivers" installname="i8042prt.sys">
|
||||||
<bootstrap installbase="$(CDOUTPUT)" />
|
<bootstrap installbase="$(CDOUTPUT)" />
|
||||||
<include base="i8042prt">.</include>
|
<define name="NDEBUG" />
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
|
<file>createclose.c</file>
|
||||||
<file>i8042prt.c</file>
|
<file>i8042prt.c</file>
|
||||||
<file>keyboard.c</file>
|
<file>keyboard.c</file>
|
||||||
|
<file>misc.c</file>
|
||||||
<file>mouse.c</file>
|
<file>mouse.c</file>
|
||||||
|
<file>pnp.c</file>
|
||||||
<file>ps2pp.c</file>
|
<file>ps2pp.c</file>
|
||||||
|
<file>readwrite.c</file>
|
||||||
<file>registry.c</file>
|
<file>registry.c</file>
|
||||||
|
<file>setup.c</file>
|
||||||
<file>i8042prt.rc</file>
|
<file>i8042prt.rc</file>
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#define REACTOS_VERSION_DLL
|
#define REACTOS_VERSION_DLL
|
||||||
#define REACTOS_STR_FILE_DESCRIPTION "I8042 Port Device Driver\0"
|
#define REACTOS_STR_FILE_DESCRIPTION "i8042 Port Device Driver\0"
|
||||||
#define REACTOS_STR_INTERNAL_NAME "i8042prt\0"
|
#define REACTOS_STR_INTERNAL_NAME "i8042prt\0"
|
||||||
#define REACTOS_STR_ORIGINAL_FILENAME "i8042prt.sys\0"
|
#define REACTOS_STR_ORIGINAL_FILENAME "i8042prt.sys\0"
|
||||||
#include <reactos/version.rc>
|
#include <reactos/version.rc>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
112
reactos/drivers/input/i8042prt/misc.c
Normal file
112
reactos/drivers/input/i8042prt/misc.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/input/i8042prt/misc.c
|
||||||
|
* PURPOSE: Misceallenous operations
|
||||||
|
* PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion;
|
||||||
|
|
||||||
|
static NTSTATUS NTAPI
|
||||||
|
ForwardIrpAndWaitCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
if (Irp->PendingReturned)
|
||||||
|
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
ForwardIrpAndWait(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||||
|
KEVENT Event;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
ASSERT(LowerDevice);
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
|
||||||
|
DPRINT("Calling lower device %p\n", LowerDevice);
|
||||||
|
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
Status = IoCallDriver(LowerDevice, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
ForwardIrpAndForget(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||||
|
|
||||||
|
ASSERT(LowerDevice);
|
||||||
|
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(LowerDevice, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DuplicateUnicodeString(
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN PCUNICODE_STRING SourceString,
|
||||||
|
OUT PUNICODE_STRING DestinationString)
|
||||||
|
{
|
||||||
|
if (SourceString == NULL || DestinationString == NULL
|
||||||
|
|| SourceString->Length > SourceString->MaximumLength
|
||||||
|
|| (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL)
|
||||||
|
|| Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((SourceString->Length == 0)
|
||||||
|
&& (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
|
||||||
|
RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
|
||||||
|
{
|
||||||
|
DestinationString->Length = 0;
|
||||||
|
DestinationString->MaximumLength = 0;
|
||||||
|
DestinationString->Buffer = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
USHORT DestMaxLength = SourceString->Length;
|
||||||
|
|
||||||
|
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
|
||||||
|
DestMaxLength += sizeof(UNICODE_NULL);
|
||||||
|
|
||||||
|
DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, I8042PRT_TAG);
|
||||||
|
if (DestinationString->Buffer == NULL)
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
|
||||||
|
DestinationString->Length = SourceString->Length;
|
||||||
|
DestinationString->MaximumLength = DestMaxLength;
|
||||||
|
|
||||||
|
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
|
||||||
|
DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
684
reactos/drivers/input/i8042prt/pnp.c
Normal file
684
reactos/drivers/input/i8042prt/pnp.c
Normal file
|
@ -0,0 +1,684 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/input/i8042prt/pnp.c
|
||||||
|
* PURPOSE: IRP_MJ_PNP operations
|
||||||
|
* PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
/* This is all pretty confusing. There's more than one way to
|
||||||
|
* disable/enable the keyboard. You can send KBD_ENABLE to the
|
||||||
|
* keyboard, and it will start scanning keys. Sending KBD_DISABLE
|
||||||
|
* will disable the key scanning but also reset the parameters to
|
||||||
|
* defaults.
|
||||||
|
*
|
||||||
|
* You can also send 0xAE to the controller for enabling the
|
||||||
|
* keyboard clock line and 0xAD for disabling it. Then it'll
|
||||||
|
* automatically get turned on at the next command. The last
|
||||||
|
* way is by modifying the bit that drives the clock line in the
|
||||||
|
* 'command byte' of the controller. This is almost, but not quite,
|
||||||
|
* the same as the AE/AD thing. The difference can be used to detect
|
||||||
|
* some really old broken keyboard controllers which I hope won't be
|
||||||
|
* necessary.
|
||||||
|
*
|
||||||
|
* We change the command byte, sending KBD_ENABLE/DISABLE seems to confuse
|
||||||
|
* some kvm switches.
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
i8042ChangeMode(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR FlagsToDisable,
|
||||||
|
IN UCHAR FlagsToEnable)
|
||||||
|
{
|
||||||
|
UCHAR Value;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, KBD_READ_MODE))
|
||||||
|
{
|
||||||
|
DPRINT1("Can't read i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = i8042ReadDataWait(DeviceExtension, &Value);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("No response after read i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value &= ~FlagsToDisable;
|
||||||
|
Value |= FlagsToEnable;
|
||||||
|
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, KBD_WRITE_MODE))
|
||||||
|
{
|
||||||
|
DPRINT1("Can't set i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Value))
|
||||||
|
{
|
||||||
|
DPRINT1("Can't send i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
i8042BasicDetect(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
UCHAR Value = 0;
|
||||||
|
|
||||||
|
/* Don't enable keyboard and mouse interrupts, disable keyboard/mouse */
|
||||||
|
if (!i8042ChangeMode(DeviceExtension, CCB_KBD_INT_ENAB | CCB_MOUSE_INT_ENAB, CCB_KBD_DISAB | CCB_MOUSE_DISAB))
|
||||||
|
return STATUS_IO_DEVICE_ERROR;
|
||||||
|
|
||||||
|
i8042Flush(DeviceExtension);
|
||||||
|
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST))
|
||||||
|
{
|
||||||
|
DPRINT1("Writing CTRL_SELF_TEST command failed\n");
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = i8042ReadDataWait(DeviceExtension, &Value);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to read CTRL_SELF_TEST response, status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Value != 0x55)
|
||||||
|
{
|
||||||
|
DPRINT1("Got 0x%02x instead of 0x55\n", Value);
|
||||||
|
return STATUS_IO_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We used to send a KBD_LINE_TEST (0xAB) command here, but on at least HP
|
||||||
|
* Pavilion notebooks the response to that command was incorrect.
|
||||||
|
* So now we just assume that a keyboard is attached.
|
||||||
|
*/
|
||||||
|
DeviceExtension->Flags |= KEYBOARD_PRESENT;
|
||||||
|
|
||||||
|
if (i8042Write(DeviceExtension, DeviceExtension->ControlPort, MOUSE_LINE_TEST))
|
||||||
|
{
|
||||||
|
Status = i8042ReadDataWait(DeviceExtension, &Value);
|
||||||
|
if (NT_SUCCESS(Status) && Value == 0)
|
||||||
|
DeviceExtension->Flags |= MOUSE_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsFirstStageSetup())
|
||||||
|
/* Ignore the mouse */
|
||||||
|
DeviceExtension->Flags &= ~MOUSE_PRESENT;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
i8042DetectKeyboard(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Set LEDs (that is not fatal if some error occurs) */
|
||||||
|
Status = i8042SynchWritePort(DeviceExtension, 0, KBD_CMD_SET_LEDS, TRUE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = i8042SynchWritePort(DeviceExtension, 0, 0, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Can't finish SET_LEDS (0x%08lx)\n", Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Warning: can't write SET_LEDS (0x%08lx)\n", Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn on translation and SF (Some machines don't reboot if SF is not set) */
|
||||||
|
if (!i8042ChangeMode(DeviceExtension, 0, CCB_TRANSLATE | CCB_SYSTEM_FLAG))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
i8042DetectMouse(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
BOOLEAN Ok = FALSE;
|
||||||
|
NTSTATUS Status;
|
||||||
|
UCHAR Value;
|
||||||
|
UCHAR ExpectedReply[] = { MOUSE_ACK, 0xAA, 0x00 };
|
||||||
|
UCHAR ReplyByte;
|
||||||
|
|
||||||
|
i8042Flush(DeviceExtension);
|
||||||
|
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_WRITE_MOUSE)
|
||||||
|
||!i8042Write(DeviceExtension, DeviceExtension->DataPort, MOU_CMD_RESET))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to write reset command to mouse\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ReplyByte = 0;
|
||||||
|
ReplyByte < sizeof(ExpectedReply) / sizeof(ExpectedReply[0]);
|
||||||
|
ReplyByte++)
|
||||||
|
{
|
||||||
|
ULONG Counter = 500;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Status = i8042ReadDataWait(DeviceExtension, &Value);
|
||||||
|
} while (Status == STATUS_IO_TIMEOUT && Counter--);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("No ACK after mouse reset, status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
else if (Value != ExpectedReply[ReplyByte])
|
||||||
|
{
|
||||||
|
DPRINT1("Unexpected reply: 0x%02x (expected 0x%02x)\n",
|
||||||
|
Value, ExpectedReply[ReplyByte]);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok = TRUE;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (!Ok)
|
||||||
|
{
|
||||||
|
/* There is probably no mouse present. On some systems,
|
||||||
|
the probe locks the entire keyboard controller. Let's
|
||||||
|
try to get access to the keyboard again by sending a
|
||||||
|
reset */
|
||||||
|
i8042Flush(DeviceExtension);
|
||||||
|
i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST);
|
||||||
|
i8042ReadDataWait(DeviceExtension, &Value);
|
||||||
|
i8042Flush(DeviceExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Mouse %sdetected\n", Ok ? "" : "not ");
|
||||||
|
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
i8042ConnectKeyboardInterrupt(
|
||||||
|
IN PI8042_KEYBOARD_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
PPORT_DEVICE_EXTENSION PortDeviceExtension;
|
||||||
|
KIRQL DirqlMax;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("i8042ConnectKeyboardInterrupt()\n");
|
||||||
|
|
||||||
|
PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
|
||||||
|
DirqlMax = MAX(
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Dirql,
|
||||||
|
PortDeviceExtension->MouseInterrupt.Dirql);
|
||||||
|
|
||||||
|
DPRINT("KeyboardInterrupt.Vector %lu\n",
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Vector);
|
||||||
|
DPRINT("KeyboardInterrupt.Dirql %lu\n",
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Dirql);
|
||||||
|
DPRINT("KeyboardInterrupt.DirqlMax %lu\n",
|
||||||
|
DirqlMax);
|
||||||
|
DPRINT("KeyboardInterrupt.InterruptMode %s\n",
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched");
|
||||||
|
DPRINT("KeyboardInterrupt.ShareInterrupt %s\n",
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.ShareInterrupt ? "yes" : "no");
|
||||||
|
DPRINT("KeyboardInterrupt.Affinity 0x%lx\n",
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Affinity);
|
||||||
|
Status = IoConnectInterrupt(
|
||||||
|
&PortDeviceExtension->KeyboardInterrupt.Object,
|
||||||
|
i8042KbdInterruptService,
|
||||||
|
DeviceExtension, &PortDeviceExtension->SpinLock,
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Vector, PortDeviceExtension->KeyboardInterrupt.Dirql, DirqlMax,
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.InterruptMode, PortDeviceExtension->KeyboardInterrupt.ShareInterrupt,
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Affinity, FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoConnectInterrupt() failed with status 0x%08x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DirqlMax == PortDeviceExtension->KeyboardInterrupt.Dirql)
|
||||||
|
PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object;
|
||||||
|
PortDeviceExtension->Flags |= KEYBOARD_INITIALIZED;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
i8042ConnectMouseInterrupt(
|
||||||
|
IN PI8042_MOUSE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
PPORT_DEVICE_EXTENSION PortDeviceExtension;
|
||||||
|
KIRQL DirqlMax;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("i8042ConnectMouseInterrupt()\n");
|
||||||
|
|
||||||
|
Status = i8042MouInitialize(DeviceExtension);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
|
||||||
|
DirqlMax = MAX(
|
||||||
|
PortDeviceExtension->KeyboardInterrupt.Dirql,
|
||||||
|
PortDeviceExtension->MouseInterrupt.Dirql);
|
||||||
|
|
||||||
|
DPRINT("MouseInterrupt.Vector %lu\n",
|
||||||
|
PortDeviceExtension->MouseInterrupt.Vector);
|
||||||
|
DPRINT("MouseInterrupt.Dirql %lu\n",
|
||||||
|
PortDeviceExtension->MouseInterrupt.Dirql);
|
||||||
|
DPRINT("MouseInterrupt.DirqlMax %lu\n",
|
||||||
|
DirqlMax);
|
||||||
|
DPRINT("MouseInterrupt.InterruptMode %s\n",
|
||||||
|
PortDeviceExtension->MouseInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched");
|
||||||
|
DPRINT("MouseInterrupt.ShareInterrupt %s\n",
|
||||||
|
PortDeviceExtension->MouseInterrupt.ShareInterrupt ? "yes" : "no");
|
||||||
|
DPRINT("MouseInterrupt.Affinity 0x%lx\n",
|
||||||
|
PortDeviceExtension->MouseInterrupt.Affinity);
|
||||||
|
Status = IoConnectInterrupt(
|
||||||
|
&PortDeviceExtension->MouseInterrupt.Object,
|
||||||
|
i8042MouInterruptService,
|
||||||
|
DeviceExtension, &PortDeviceExtension->SpinLock,
|
||||||
|
PortDeviceExtension->MouseInterrupt.Vector, PortDeviceExtension->MouseInterrupt.Dirql, DirqlMax,
|
||||||
|
PortDeviceExtension->MouseInterrupt.InterruptMode, PortDeviceExtension->MouseInterrupt.ShareInterrupt,
|
||||||
|
PortDeviceExtension->MouseInterrupt.Affinity, FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoConnectInterrupt() failed with status 0x%08x\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DirqlMax == PortDeviceExtension->MouseInterrupt.Dirql)
|
||||||
|
PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->MouseInterrupt.Object;
|
||||||
|
|
||||||
|
PortDeviceExtension->Flags |= MOUSE_INITIALIZED;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
PortDeviceExtension->Flags &= ~MOUSE_INITIALIZED;
|
||||||
|
if (PortDeviceExtension->MouseInterrupt.Object)
|
||||||
|
{
|
||||||
|
IoDisconnectInterrupt(PortDeviceExtension->MouseInterrupt.Object);
|
||||||
|
PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
EnableInterrupts(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
UCHAR FlagsToDisable = 0;
|
||||||
|
UCHAR FlagsToEnable = 0;
|
||||||
|
|
||||||
|
i8042Flush(DeviceExtension);
|
||||||
|
|
||||||
|
/* Select the devices we have */
|
||||||
|
if (DeviceExtension->Flags & KEYBOARD_PRESENT)
|
||||||
|
{
|
||||||
|
FlagsToDisable |= CCB_KBD_DISAB;
|
||||||
|
FlagsToEnable |= CCB_KBD_INT_ENAB;
|
||||||
|
}
|
||||||
|
if (DeviceExtension->Flags & MOUSE_PRESENT)
|
||||||
|
{
|
||||||
|
FlagsToDisable |= CCB_MOUSE_DISAB;
|
||||||
|
FlagsToEnable |= CCB_MOUSE_INT_ENAB;
|
||||||
|
}
|
||||||
|
if (!i8042ChangeMode(DeviceExtension, FlagsToDisable, FlagsToEnable))
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
StartProcedure(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (DeviceExtension->DataPort == 0)
|
||||||
|
{
|
||||||
|
/* Unable to do something at the moment */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_PRESENT)))
|
||||||
|
{
|
||||||
|
/* Try to detect them */
|
||||||
|
DPRINT("Check if the controller is really a i8042\n");
|
||||||
|
Status = i8042BasicDetect(DeviceExtension);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("i8042BasicDetect() failed with status 0x%08lx\n", Status);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
DPRINT("Detecting keyboard\n");
|
||||||
|
if (!i8042DetectKeyboard(DeviceExtension))
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
DPRINT("Detecting mouse\n");
|
||||||
|
if (!i8042DetectMouse(DeviceExtension))
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
DPRINT("Keyboard present: %s\n", DeviceExtension->Flags & KEYBOARD_PRESENT ? "YES" : "NO");
|
||||||
|
DPRINT("Mouse present : %s\n", DeviceExtension->Flags & MOUSE_PRESENT ? "YES" : "NO");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect interrupts */
|
||||||
|
if (DeviceExtension->Flags & KEYBOARD_PRESENT &&
|
||||||
|
DeviceExtension->Flags & KEYBOARD_CONNECTED &&
|
||||||
|
DeviceExtension->Flags & KEYBOARD_STARTED &&
|
||||||
|
!(DeviceExtension->Flags & (MOUSE_PRESENT | KEYBOARD_INITIALIZED)))
|
||||||
|
{
|
||||||
|
/* No mouse, and the keyboard is ready */
|
||||||
|
Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceExtension->Flags |= KEYBOARD_INITIALIZED;
|
||||||
|
Status = EnableInterrupts(DeviceExtension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DeviceExtension->Flags & MOUSE_PRESENT &&
|
||||||
|
DeviceExtension->Flags & MOUSE_CONNECTED &&
|
||||||
|
DeviceExtension->Flags & MOUSE_STARTED &&
|
||||||
|
!(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_INITIALIZED)))
|
||||||
|
{
|
||||||
|
/* No keyboard, and the mouse is ready */
|
||||||
|
Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceExtension->Flags |= MOUSE_INITIALIZED;
|
||||||
|
Status = EnableInterrupts(DeviceExtension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DeviceExtension->Flags & KEYBOARD_PRESENT &&
|
||||||
|
DeviceExtension->Flags & KEYBOARD_CONNECTED &&
|
||||||
|
DeviceExtension->Flags & KEYBOARD_STARTED &&
|
||||||
|
DeviceExtension->Flags & MOUSE_PRESENT &&
|
||||||
|
DeviceExtension->Flags & MOUSE_CONNECTED &&
|
||||||
|
DeviceExtension->Flags & MOUSE_STARTED &&
|
||||||
|
!(DeviceExtension->Flags & (KEYBOARD_INITIALIZED | MOUSE_INITIALIZED)))
|
||||||
|
{
|
||||||
|
/* The keyboard and mouse are ready */
|
||||||
|
Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceExtension->Flags |= KEYBOARD_INITIALIZED;
|
||||||
|
Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceExtension->Flags |= MOUSE_INITIALIZED;
|
||||||
|
Status = EnableInterrupts(DeviceExtension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
i8042PnpStartDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PCM_RESOURCE_LIST AllocatedResources,
|
||||||
|
IN PCM_RESOURCE_LIST AllocatedResourcesTranslated)
|
||||||
|
{
|
||||||
|
PFDO_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
PPORT_DEVICE_EXTENSION PortDeviceExtension;
|
||||||
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor, ResourceDescriptorTranslated;
|
||||||
|
INTERRUPT_DATA InterruptData;
|
||||||
|
BOOLEAN FoundDataPort = FALSE;
|
||||||
|
BOOLEAN FoundControlPort = FALSE;
|
||||||
|
BOOLEAN FoundIrq = FALSE;
|
||||||
|
ULONG i;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("i8042PnpStartDevice(%p)\n", DeviceObject);
|
||||||
|
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
PortDeviceExtension = DeviceExtension->PortDeviceExtension;
|
||||||
|
|
||||||
|
ASSERT(DeviceExtension->PnpState == dsStopped);
|
||||||
|
|
||||||
|
if (!AllocatedResources)
|
||||||
|
{
|
||||||
|
DPRINT("No allocated resources sent to driver\n");
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
if (AllocatedResources->Count != 1)
|
||||||
|
{
|
||||||
|
DPRINT("Wrong number of allocated resources sent to driver\n");
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
if (AllocatedResources->List[0].PartialResourceList.Version != 1
|
||||||
|
|| AllocatedResources->List[0].PartialResourceList.Revision != 1
|
||||||
|
|| AllocatedResourcesTranslated->List[0].PartialResourceList.Version != 1
|
||||||
|
|| AllocatedResourcesTranslated->List[0].PartialResourceList.Revision != 1)
|
||||||
|
{
|
||||||
|
DPRINT("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
|
||||||
|
AllocatedResources->List[0].PartialResourceList.Version,
|
||||||
|
AllocatedResources->List[0].PartialResourceList.Revision,
|
||||||
|
AllocatedResourcesTranslated->List[0].PartialResourceList.Version,
|
||||||
|
AllocatedResourcesTranslated->List[0].PartialResourceList.Revision);
|
||||||
|
return STATUS_REVISION_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Irq and optionally control port and data port */
|
||||||
|
for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++)
|
||||||
|
{
|
||||||
|
ResourceDescriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i];
|
||||||
|
ResourceDescriptorTranslated = &AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
|
||||||
|
switch (ResourceDescriptor->Type)
|
||||||
|
{
|
||||||
|
case CmResourceTypePort:
|
||||||
|
{
|
||||||
|
if (ResourceDescriptor->u.Port.Length == 1)
|
||||||
|
{
|
||||||
|
/* We assume that the first ressource will
|
||||||
|
* be the control port and the second one
|
||||||
|
* will be the data port...
|
||||||
|
*/
|
||||||
|
if (!FoundDataPort)
|
||||||
|
{
|
||||||
|
PortDeviceExtension->DataPort = ULongToPtr(ResourceDescriptor->u.Port.Start.u.LowPart);
|
||||||
|
DPRINT("Found data port: 0x%lx\n", PortDeviceExtension->DataPort);
|
||||||
|
FoundDataPort = TRUE;
|
||||||
|
}
|
||||||
|
else if (!FoundControlPort)
|
||||||
|
{
|
||||||
|
PortDeviceExtension->ControlPort = ULongToPtr(ResourceDescriptor->u.Port.Start.u.LowPart);
|
||||||
|
DPRINT("Found control port: 0x%lx\n", PortDeviceExtension->ControlPort);
|
||||||
|
FoundControlPort = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Too much I/O ranges provided\n", ResourceDescriptor->u.Port.Length);
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DPRINT1("Invalid I/O range length: 0x%lx\n", ResourceDescriptor->u.Port.Length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CmResourceTypeInterrupt:
|
||||||
|
{
|
||||||
|
if (FoundIrq)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
InterruptData.Dirql = (KIRQL)ResourceDescriptorTranslated->u.Interrupt.Level;
|
||||||
|
InterruptData.Vector = ResourceDescriptorTranslated->u.Interrupt.Vector;
|
||||||
|
InterruptData.Affinity = ResourceDescriptorTranslated->u.Interrupt.Affinity;
|
||||||
|
if (ResourceDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
|
||||||
|
InterruptData.InterruptMode = Latched;
|
||||||
|
else
|
||||||
|
InterruptData.InterruptMode = LevelSensitive;
|
||||||
|
InterruptData.ShareInterrupt = (ResourceDescriptorTranslated->ShareDisposition == CmResourceShareShared);
|
||||||
|
DPRINT("Found irq resource: %lu\n", ResourceDescriptor->u.Interrupt.Vector);
|
||||||
|
FoundIrq = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DPRINT("Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FoundIrq)
|
||||||
|
{
|
||||||
|
DPRINT("Interrupt resource was not found in allocated resources list\n");
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
else if (DeviceExtension->Type == Keyboard && (!FoundDataPort || !FoundControlPort))
|
||||||
|
{
|
||||||
|
DPRINT("Some required resources were not found in allocated resources list\n");
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
else if (DeviceExtension->Type == Mouse && (FoundDataPort || FoundControlPort))
|
||||||
|
{
|
||||||
|
DPRINT("Too much resources were provided in allocated resources list\n");
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (DeviceExtension->Type)
|
||||||
|
{
|
||||||
|
case Keyboard:
|
||||||
|
{
|
||||||
|
RtlCopyMemory(
|
||||||
|
&PortDeviceExtension->KeyboardInterrupt,
|
||||||
|
&InterruptData,
|
||||||
|
sizeof(INTERRUPT_DATA));
|
||||||
|
PortDeviceExtension->Flags |= KEYBOARD_STARTED;
|
||||||
|
Status = StartProcedure(PortDeviceExtension);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Mouse:
|
||||||
|
{
|
||||||
|
RtlCopyMemory(
|
||||||
|
&PortDeviceExtension->MouseInterrupt,
|
||||||
|
&InterruptData,
|
||||||
|
sizeof(INTERRUPT_DATA));
|
||||||
|
PortDeviceExtension->Flags |= MOUSE_STARTED;
|
||||||
|
Status = StartProcedure(PortDeviceExtension);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
DPRINT1("Unknown FDO type %u\n", DeviceExtension->Type);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
DeviceExtension->PnpState = dsStarted;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
i8042Pnp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
ULONG MinorFunction;
|
||||||
|
I8042_DEVICE_TYPE DeviceType;
|
||||||
|
ULONG_PTR Information = 0;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
MinorFunction = Stack->MinorFunction;
|
||||||
|
DeviceType = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Type;
|
||||||
|
|
||||||
|
switch (MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_START_DEVICE: /* 0x00 */
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
||||||
|
|
||||||
|
/* Call lower driver (if any) */
|
||||||
|
if (DeviceType != PhysicalDeviceObject)
|
||||||
|
{
|
||||||
|
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Status = i8042PnpStartDevice(
|
||||||
|
DeviceObject,
|
||||||
|
Stack->Parameters.StartDevice.AllocatedResources,
|
||||||
|
Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x07 */
|
||||||
|
{
|
||||||
|
switch (Stack->Parameters.QueryDeviceRelations.Type)
|
||||||
|
{
|
||||||
|
case BusRelations:
|
||||||
|
{
|
||||||
|
PDEVICE_RELATIONS DeviceRelations;
|
||||||
|
|
||||||
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
|
||||||
|
DeviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), I8042PRT_TAG);
|
||||||
|
if (DeviceRelations)
|
||||||
|
{
|
||||||
|
DeviceRelations->Count = 0;
|
||||||
|
Information = (ULONG_PTR)DeviceRelations;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RemovalRelations:
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
|
||||||
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
|
||||||
|
Stack->Parameters.QueryDeviceRelations.Type);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0x0d */
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
|
||||||
|
/* Nothing to do */
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
DPRINT1("IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = Information;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -1,136 +1,138 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
* PROJECT: ReactOS kernel
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: drivers/input/i8042prt/ps2pp.c
|
* FILE: drivers/input/i8042prt/ps2pp.c
|
||||||
* PURPOSE: i8042prt driver
|
* PURPOSE: ps2pp protocol handling
|
||||||
* ps2pp protocol handling
|
* PROGRAMMERS: Copyright Martijn Vernooij (o112w8r02@sneakemail.com)
|
||||||
* PROGRAMMER: Tinus
|
* Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
#include "i8042prt.h"
|
#include "i8042prt.h"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
/* FUNCTIONS *****************************************************************/
|
||||||
#define NDEBUG
|
|
||||||
#endif
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input)
|
VOID
|
||||||
|
i8042MouHandlePs2pp(
|
||||||
|
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Input)
|
||||||
{
|
{
|
||||||
UCHAR PktType;
|
UCHAR PktType;
|
||||||
PMOUSE_INPUT_DATA MouseInput = DevExt->MouseBuffer +
|
PMOUSE_INPUT_DATA MouseInput;
|
||||||
DevExt->MouseInBuffer;
|
|
||||||
|
|
||||||
/* First, collect 3 bytes for a packet
|
MouseInput = DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer;
|
||||||
* We can detect out-of-sync only by checking
|
|
||||||
* the whole packet anyway.
|
|
||||||
*
|
|
||||||
* If bit 7 and 8 of the first byte are 0, its
|
|
||||||
* a normal packet.
|
|
||||||
*
|
|
||||||
* Otherwise, the packet is different, like this:
|
|
||||||
* 1: E 1 b3 b2 x x x x
|
|
||||||
* 2: x x b1 b0 x1 x0 1 0
|
|
||||||
* 3: x x x x x x x1 x0
|
|
||||||
*
|
|
||||||
* b3-0 form a code that specifies the packet type:
|
|
||||||
*
|
|
||||||
* 0 Device Type
|
|
||||||
* 1 Rollers and buttons
|
|
||||||
* 2 Reserved
|
|
||||||
* 3 Reserved
|
|
||||||
* 4 Device ID
|
|
||||||
* 5 Channel & Battery
|
|
||||||
* 6 Wireless notifications
|
|
||||||
* 7 Reserved
|
|
||||||
* 8 ShortID LSB (ShortID is a number that is supposed to differentiate
|
|
||||||
* 9 ShortID MSB between your mouse and your neighbours')
|
|
||||||
* 10 Reserved
|
|
||||||
* 11 Mouse capabilities
|
|
||||||
* 12 Remote control LSB
|
|
||||||
* 13 Remote control MSB
|
|
||||||
* 14 Reserved
|
|
||||||
* 15 Extended packet
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (DevExt->MouseState) {
|
/* First, collect 3 bytes for a packet
|
||||||
case MouseIdle:
|
* We can detect out-of-sync only by checking
|
||||||
case XMovement:
|
* the whole packet anyway.
|
||||||
DevExt->MouseLogiBuffer[DevExt->MouseState] = Input;
|
*
|
||||||
DevExt->MouseState++;
|
* If bit 7 and 8 of the first byte are 0, its
|
||||||
break;
|
* a normal packet.
|
||||||
|
*
|
||||||
|
* Otherwise, the packet is different, like this:
|
||||||
|
* 1: E 1 b3 b2 x x x x
|
||||||
|
* 2: x x b1 b0 x1 x0 1 0
|
||||||
|
* 3: x x x x x x x1 x0
|
||||||
|
*
|
||||||
|
* b3-0 form a code that specifies the packet type:
|
||||||
|
*
|
||||||
|
* 0 Device Type
|
||||||
|
* 1 Rollers and buttons
|
||||||
|
* 2 Reserved
|
||||||
|
* 3 Reserved
|
||||||
|
* 4 Device ID
|
||||||
|
* 5 Channel & Battery
|
||||||
|
* 6 Wireless notifications
|
||||||
|
* 7 Reserved
|
||||||
|
* 8 ShortID LSB (ShortID is a number that is supposed to differentiate
|
||||||
|
* 9 ShortID MSB between your mouse and your neighbours')
|
||||||
|
* 10 Reserved
|
||||||
|
* 11 Mouse capabilities
|
||||||
|
* 12 Remote control LSB
|
||||||
|
* 13 Remote control MSB
|
||||||
|
* 14 Reserved
|
||||||
|
* 15 Extended packet
|
||||||
|
*/
|
||||||
|
|
||||||
case YMovement:
|
switch (DeviceExtension->MouseState)
|
||||||
DevExt->MouseLogiBuffer[2] = Input;
|
{
|
||||||
DevExt->MouseState = MouseIdle;
|
case MouseIdle:
|
||||||
|
case XMovement:
|
||||||
|
DeviceExtension->MouseLogiBuffer[DeviceExtension->MouseState] = Input;
|
||||||
|
DeviceExtension->MouseState++;
|
||||||
|
break;
|
||||||
|
|
||||||
/* first check if it's a normal packet */
|
case YMovement:
|
||||||
|
DeviceExtension->MouseLogiBuffer[2] = Input;
|
||||||
|
DeviceExtension->MouseState = MouseIdle;
|
||||||
|
|
||||||
if (!(DevExt->MouseLogiBuffer[0] & 0xC0)) {
|
/* first check if it's a normal packet */
|
||||||
DevExt->MouseState = MouseIdle;
|
|
||||||
I8042MouseHandle(DevExt, DevExt->MouseLogiBuffer[0]);
|
|
||||||
I8042MouseHandle(DevExt, DevExt->MouseLogiBuffer[1]);
|
|
||||||
I8042MouseHandle(DevExt, DevExt->MouseLogiBuffer[2]);
|
|
||||||
/* We could care about wether MouseState really
|
|
||||||
* advances, but we don't need to because we're
|
|
||||||
* only doing three bytes anyway, so the packet
|
|
||||||
* will never complete if it's broken.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sanity check */
|
if (!(DeviceExtension->MouseLogiBuffer[0] & 0xC0))
|
||||||
|
{
|
||||||
if (((DevExt->MouseLogiBuffer[0] & 0x48) != 0x48) ||
|
DeviceExtension->MouseState = MouseIdle;
|
||||||
(((DevExt->MouseLogiBuffer[1] & 0x0C) >> 2) !=
|
i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[0]);
|
||||||
(DevExt->MouseLogiBuffer[2] & 0x03))) {
|
i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[1]);
|
||||||
DPRINT1("Ps2pp packet fails sanity checks\n");
|
i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[2]);
|
||||||
return;
|
/* We could care about wether MouseState really
|
||||||
}
|
* advances, but we don't need to because we're
|
||||||
|
* only doing three bytes anyway, so the packet
|
||||||
/* Now get the packet type */
|
* will never complete if it's broken.
|
||||||
|
*/
|
||||||
PktType = ((DevExt->MouseLogiBuffer[0] & 0x30) >> 4) &
|
return;
|
||||||
((DevExt->MouseLogiBuffer[1] & 0x30) >> 6);
|
|
||||||
|
|
||||||
switch (PktType) {
|
|
||||||
case 0:
|
|
||||||
/* The packet contains the device ID, but we
|
|
||||||
* already read that in the initialization
|
|
||||||
* sequence. Ignore it.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
RtlZeroMemory(MouseInput, sizeof(MOUSE_INPUT_DATA));
|
|
||||||
if (DevExt->MouseLogiBuffer[2] & 0x10)
|
|
||||||
MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN;
|
|
||||||
|
|
||||||
if (DevExt->MouseLogiBuffer[2] & 0x20)
|
|
||||||
MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN;
|
|
||||||
|
|
||||||
if (DevExt->MouseLogiBuffer[2] & 0x0F) {
|
|
||||||
MouseInput->ButtonFlags |= MOUSE_WHEEL;
|
|
||||||
if (DevExt->MouseLogiBuffer[2] & 0x08)
|
|
||||||
MouseInput->ButtonData =
|
|
||||||
(DevExt->MouseLogiBuffer[2] & 0x07) -
|
|
||||||
8;
|
|
||||||
else
|
|
||||||
MouseInput->ButtonData =
|
|
||||||
DevExt->MouseLogiBuffer[2] & 0x07;
|
|
||||||
}
|
}
|
||||||
I8042MouseHandleButtons(DevExt, MOUSE_BUTTON_4_DOWN |
|
|
||||||
MOUSE_BUTTON_5_DOWN);
|
/* sanity check */
|
||||||
I8042QueueMousePacket(
|
if (((DeviceExtension->MouseLogiBuffer[0] & 0x48) != 0x48) ||
|
||||||
DevExt->MouseObject);
|
(((DeviceExtension->MouseLogiBuffer[1] & 0x0C) >> 2) !=
|
||||||
return;
|
(DeviceExtension->MouseLogiBuffer[2] & 0x03)))
|
||||||
|
{
|
||||||
|
DPRINT1("Ps2pp packet fails sanity checks\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the packet type */
|
||||||
|
PktType = ((DeviceExtension->MouseLogiBuffer[0] & 0x30) >> 4) &
|
||||||
|
((DeviceExtension->MouseLogiBuffer[1] & 0x30) >> 6);
|
||||||
|
|
||||||
|
switch (PktType)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* The packet contains the device ID, but we
|
||||||
|
* already read that in the initialization
|
||||||
|
* sequence. Ignore it.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
RtlZeroMemory(MouseInput, sizeof(MOUSE_INPUT_DATA));
|
||||||
|
if (DeviceExtension->MouseLogiBuffer[2] & 0x10)
|
||||||
|
MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN;
|
||||||
|
|
||||||
|
if (DeviceExtension->MouseLogiBuffer[2] & 0x20)
|
||||||
|
MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN;
|
||||||
|
|
||||||
|
if (DeviceExtension->MouseLogiBuffer[2] & 0x0F)
|
||||||
|
{
|
||||||
|
MouseInput->ButtonFlags |= MOUSE_WHEEL;
|
||||||
|
if (DeviceExtension->MouseLogiBuffer[2] & 0x08)
|
||||||
|
MouseInput->ButtonData = (DeviceExtension->MouseLogiBuffer[2] & 0x07) - 8;
|
||||||
|
else
|
||||||
|
MouseInput->ButtonData = DeviceExtension->MouseLogiBuffer[2] & 0x07;
|
||||||
|
}
|
||||||
|
i8042MouHandleButtons(
|
||||||
|
DeviceExtension,
|
||||||
|
MOUSE_BUTTON_4_DOWN | MOUSE_BUTTON_5_DOWN);
|
||||||
|
DeviceExtension->MouseHook.QueueMousePacket(DeviceExtension->MouseHook.CallContext);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
/* These are for things that would probably
|
||||||
|
* be handled by logitechs own driver.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* These are for things that would probably
|
DPRINT1("Unexpected input state for ps2pp!\n");
|
||||||
* be handled by logitechs own driver.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
DPRINT1("Unexpected input state for ps2pp!\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
212
reactos/drivers/input/i8042prt/readwrite.c
Normal file
212
reactos/drivers/input/i8042prt/readwrite.c
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/input/i8042prt/readwrite.c
|
||||||
|
* PURPOSE: Read/write port functions
|
||||||
|
* PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com)
|
||||||
|
Copyright Jason Filby (jasonfilby@yahoo.com)
|
||||||
|
Copyright Martijn Vernooij (o112w8r02@sneakemail.com)
|
||||||
|
Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
i8042Flush(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
UCHAR Ignore;
|
||||||
|
|
||||||
|
while (NT_SUCCESS(i8042ReadData(DeviceExtension, KBD_OBF | MOU_OBF, &Ignore))) {
|
||||||
|
DPRINT("Data flushed\n"); /* drop */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
i8042IsrWritePort(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Value,
|
||||||
|
IN UCHAR SelectCmd OPTIONAL)
|
||||||
|
{
|
||||||
|
if (SelectCmd)
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, SelectCmd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
i8042Write(DeviceExtension, DeviceExtension->DataPort, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION: Read data from port 0x60
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
i8042ReadData(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR StatusFlags,
|
||||||
|
OUT PUCHAR Data)
|
||||||
|
{
|
||||||
|
UCHAR PortStatus;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = i8042ReadStatus(DeviceExtension, &PortStatus);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
// If data is available
|
||||||
|
if (PortStatus & StatusFlags)
|
||||||
|
{
|
||||||
|
*Data = READ_PORT_UCHAR(DeviceExtension->DataPort);
|
||||||
|
DPRINT("Read: 0x%02x (status: 0x%x)\n", Data[0], PortStatus);
|
||||||
|
|
||||||
|
// If the data is valid (not timeout, not parity error)
|
||||||
|
if ((PortStatus & KBD_PERR) == 0)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
i8042ReadStatus(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
OUT PUCHAR Status)
|
||||||
|
{
|
||||||
|
ASSERT(DeviceExtension->ControlPort != NULL);
|
||||||
|
*Status = READ_PORT_UCHAR(DeviceExtension->ControlPort);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION: Read data from data port
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
i8042ReadDataWait(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
OUT PUCHAR Data)
|
||||||
|
{
|
||||||
|
ULONG Counter;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Counter = DeviceExtension->Settings.PollingIterations;
|
||||||
|
|
||||||
|
while (Counter--)
|
||||||
|
{
|
||||||
|
Status = i8042ReadKeyboardData(DeviceExtension, Data);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
KeStallExecutionProcessor(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timed out */
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This one reads a value from the port; You don't have to specify
|
||||||
|
* which one, it'll always be from the one you talked to, so one function
|
||||||
|
* is enough this time. Note how MSDN specifies the
|
||||||
|
* WaitForAck parameter to be ignored.
|
||||||
|
*/
|
||||||
|
NTSTATUS DDKAPI
|
||||||
|
i8042SynchReadPort(
|
||||||
|
IN PVOID Context,
|
||||||
|
OUT PUCHAR Value,
|
||||||
|
IN BOOLEAN WaitForAck)
|
||||||
|
{
|
||||||
|
PPORT_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
DeviceExtension = (PPORT_DEVICE_EXTENSION)Context;
|
||||||
|
|
||||||
|
return i8042ReadDataWait(DeviceExtension, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions are callbacks for filter driver custom
|
||||||
|
* initialization routines.
|
||||||
|
*/
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
i8042SynchWritePort(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN UCHAR Port,
|
||||||
|
IN UCHAR Value,
|
||||||
|
IN BOOLEAN WaitForAck)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
UCHAR Ack;
|
||||||
|
ULONG ResendIterations;
|
||||||
|
|
||||||
|
ResendIterations = DeviceExtension->Settings.ResendIterations + 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (Port)
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Port))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to write Port\n");
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Value))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to write Value\n");
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForAck)
|
||||||
|
{
|
||||||
|
Status = i8042ReadDataWait(DeviceExtension, &Ack);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to read Ack\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
if (Ack == KBD_ACK)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
else if (Ack == KBD_RESEND)
|
||||||
|
DPRINT("i8042 asks for a data resend\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
DPRINT("Reiterating\n");
|
||||||
|
ResendIterations--;
|
||||||
|
} while (ResendIterations);
|
||||||
|
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION: Write data to a port, waiting first for it to become ready
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
i8042Write(
|
||||||
|
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PUCHAR addr,
|
||||||
|
IN UCHAR data)
|
||||||
|
{
|
||||||
|
ULONG ResendIterations;
|
||||||
|
|
||||||
|
ASSERT(addr);
|
||||||
|
ASSERT(DeviceExtension->ControlPort != NULL);
|
||||||
|
|
||||||
|
ResendIterations = DeviceExtension->Settings.ResendIterations;
|
||||||
|
|
||||||
|
while ((KBD_IBF & READ_PORT_UCHAR(DeviceExtension->ControlPort)) &&
|
||||||
|
(ResendIterations--))
|
||||||
|
{
|
||||||
|
KeStallExecutionProcessor(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ResendIterations)
|
||||||
|
{
|
||||||
|
WRITE_PORT_UCHAR(addr, data);
|
||||||
|
DPRINT("Sent 0x%x to port 0x%x\n", data, addr);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
|
@ -1,211 +1,231 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
* PROJECT: ReactOS kernel
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: drivers/input/i8042prt/registry.c
|
* FILE: drivers/input/i8042prt/i8042prt.c
|
||||||
* PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver
|
* PURPOSE: Reading the registry
|
||||||
* Reading the registry
|
* PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com)
|
||||||
* PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
|
Copyright Jason Filby (jasonfilby@yahoo.com)
|
||||||
* Jason Filby (jasonfilby@yahoo.com)
|
Copyright Martijn Vernooij (o112w8r02@sneakemail.com)
|
||||||
* Tinus
|
Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "i8042prt.h"
|
#include "i8042prt.h"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define NDEBUG
|
|
||||||
#endif
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
/*
|
NTSTATUS
|
||||||
* Read the registry keys associated with this device. The RegistryPath
|
ReadRegistryEntries(
|
||||||
* var is a hack. This should be more like what microsoft does, but I
|
IN PUNICODE_STRING RegistryPath,
|
||||||
* don't know exactly what they do except that it's a hack too...
|
OUT PI8042_SETTINGS Settings)
|
||||||
*/
|
|
||||||
VOID STDCALL I8042ReadRegistry(PDRIVER_OBJECT DriverObject,
|
|
||||||
PDEVICE_EXTENSION DevExt)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
RTL_QUERY_REGISTRY_TABLE Parameters[19];
|
RTL_QUERY_REGISTRY_TABLE Parameters[17];
|
||||||
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
ULONG DefaultHeadless = 0;
|
ULONG DefaultKeyboardDataQueueSize = 0x64;
|
||||||
ULONG DefaultCrashScroll = 0;
|
PCWSTR DefaultKeyboardDeviceBaseName = L"KeyboardPort";
|
||||||
ULONG DefaultCrashSysRq = 0;
|
ULONG DefaultMouseDataQueueSize = 0x64;
|
||||||
ULONG DefaultReportResetErrors = 0;
|
ULONG DefaultMouseResolution = 3;
|
||||||
|
ULONG DefaultMouseSynchIn100ns = 20000000;
|
||||||
|
ULONG DefaultNumberOfButtons = 2;
|
||||||
|
PCWSTR DefaultPointerDeviceBaseName = L"PointerPort";
|
||||||
ULONG DefaultPollStatusIterations = 1;
|
ULONG DefaultPollStatusIterations = 1;
|
||||||
ULONG DefaultResendIterations = 3;
|
ULONG DefaultOverrideKeyboardType = 4;
|
||||||
|
ULONG DefaultOverrideKeyboardSubtype = 0;
|
||||||
ULONG DefaultPollingIterations = 12000;
|
ULONG DefaultPollingIterations = 12000;
|
||||||
ULONG DefaultPollingIterationsMaximum = 12000;
|
ULONG DefaultPollingIterationsMaximum = 12000;
|
||||||
ULONG DefaultKeyboardDataQueueSize = 100;
|
ULONG DefaultResendIterations = 0x3;
|
||||||
ULONG DefaultOverrideKeyboardType = 0;
|
|
||||||
ULONG DefaultOverrideKeyboardSubtype = 0;
|
|
||||||
ULONG DefaultMouseDataQueueSize = 100;
|
|
||||||
ULONG DefaultMouseResendStallTime = 1000;
|
|
||||||
ULONG DefaultMouseSynchIn100ns = 20000000;
|
|
||||||
ULONG DefaultMouseResolution = 3;
|
|
||||||
ULONG DefaultSampleRate = 60;
|
ULONG DefaultSampleRate = 60;
|
||||||
ULONG DefaultNumberOfButtons = 2;
|
ULONG DefaultCrashOnCtrlScroll;
|
||||||
ULONG DefaultEnableWheelDetection = 1;
|
|
||||||
|
/* Default value for CrashOnCtrlScroll depends if we're
|
||||||
|
* running a debug build or a normal build.
|
||||||
|
*/
|
||||||
|
#ifdef DBG
|
||||||
|
DefaultCrashOnCtrlScroll = 1;
|
||||||
|
#else
|
||||||
|
DefaultCrashOnCtrlScroll = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
RtlZeroMemory(Parameters, sizeof(Parameters));
|
RtlZeroMemory(Parameters, sizeof(Parameters));
|
||||||
|
|
||||||
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
||||||
Parameters[0].Name = L"Headless";
|
Parameters[0].Name = L"Parameters";
|
||||||
Parameters[0].EntryContext = &DevExt->Settings.Headless;
|
|
||||||
Parameters[0].DefaultType = REG_DWORD;
|
|
||||||
Parameters[0].DefaultData = &DefaultHeadless;
|
|
||||||
Parameters[0].DefaultLength = sizeof(ULONG);
|
|
||||||
|
|
||||||
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[1].Name = L"CrashOnCtrlScroll";
|
Parameters[1].Name = L"KeyboardDataQueueSize";
|
||||||
Parameters[1].EntryContext = &DevExt->Settings.CrashScroll;
|
Parameters[1].EntryContext = &Settings->KeyboardDataQueueSize;
|
||||||
Parameters[1].DefaultType = REG_DWORD;
|
Parameters[1].DefaultType = REG_DWORD;
|
||||||
Parameters[1].DefaultData = &DefaultCrashScroll;
|
Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize;
|
||||||
Parameters[1].DefaultLength = sizeof(ULONG);
|
Parameters[1].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[2].Name = L"BreakOnSysRq";
|
Parameters[2].Name = L"KeyboardDeviceBaseName";
|
||||||
Parameters[2].EntryContext = &DevExt->Settings.CrashSysRq;
|
Parameters[2].EntryContext = &Settings->KeyboardDeviceBaseName;
|
||||||
Parameters[2].DefaultType = REG_DWORD;
|
Parameters[2].DefaultType = REG_SZ;
|
||||||
Parameters[2].DefaultData = &DefaultCrashSysRq;
|
Parameters[2].DefaultData = (PVOID)DefaultKeyboardDeviceBaseName;
|
||||||
Parameters[2].DefaultLength = sizeof(ULONG);
|
Parameters[2].DefaultLength = 0;
|
||||||
|
|
||||||
Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[3].Name = L"ReportResetErrors";
|
Parameters[3].Name = L"MouseDataQueueSize";
|
||||||
Parameters[3].EntryContext = &DevExt->Settings.ReportResetErrors;
|
Parameters[3].EntryContext = &Settings->MouseDataQueueSize;
|
||||||
Parameters[3].DefaultType = REG_DWORD;
|
Parameters[3].DefaultType = REG_DWORD;
|
||||||
Parameters[3].DefaultData = &DefaultReportResetErrors;
|
Parameters[3].DefaultData = &DefaultMouseDataQueueSize;
|
||||||
Parameters[3].DefaultLength = sizeof(ULONG);
|
Parameters[3].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[4].Name = L"PollStatusIterations";
|
Parameters[4].Name = L"MouseResolution";
|
||||||
Parameters[4].EntryContext = &DevExt->Settings.PollStatusIterations;
|
Parameters[4].EntryContext = &Settings->MouseResolution;
|
||||||
Parameters[4].DefaultType = REG_DWORD;
|
Parameters[4].DefaultType = REG_DWORD;
|
||||||
Parameters[4].DefaultData = &DefaultPollStatusIterations;
|
Parameters[4].DefaultData = &DefaultMouseResolution;
|
||||||
Parameters[4].DefaultLength = sizeof(ULONG);
|
Parameters[4].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[5].Name = L"ResendIterations";
|
Parameters[5].Name = L"MouseSynchIn100ns";
|
||||||
Parameters[5].EntryContext = &DevExt->Settings.ResendIterations;
|
Parameters[5].EntryContext = &Settings->MouseSynchIn100ns;
|
||||||
Parameters[5].DefaultType = REG_DWORD;
|
Parameters[5].DefaultType = REG_DWORD;
|
||||||
Parameters[5].DefaultData = &DefaultResendIterations;
|
Parameters[5].DefaultData = &DefaultMouseSynchIn100ns;
|
||||||
Parameters[5].DefaultLength = sizeof(ULONG);
|
Parameters[5].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[6].Name = L"PollingIterations";
|
Parameters[6].Name = L"NumberOfButtons";
|
||||||
Parameters[6].EntryContext = &DevExt->Settings.PollingIterations;
|
Parameters[6].EntryContext = &Settings->NumberOfButtons;
|
||||||
Parameters[6].DefaultType = REG_DWORD;
|
Parameters[6].DefaultType = REG_DWORD;
|
||||||
Parameters[6].DefaultData = &DefaultPollingIterations;
|
Parameters[6].DefaultData = &DefaultNumberOfButtons;
|
||||||
Parameters[6].DefaultLength = sizeof(ULONG);
|
Parameters[6].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[7].Name = L"PollingIterationsMaximum";
|
Parameters[7].Name = L"PointerDeviceBaseName";
|
||||||
Parameters[7].EntryContext = &DevExt->Settings.PollingIterationsMaximum;
|
Parameters[7].EntryContext = &Settings->PointerDeviceBaseName;
|
||||||
Parameters[7].DefaultType = REG_DWORD;
|
Parameters[7].DefaultType = REG_SZ;
|
||||||
Parameters[7].DefaultData = &DefaultPollingIterationsMaximum;
|
Parameters[7].DefaultData = (PVOID)DefaultPointerDeviceBaseName;
|
||||||
Parameters[7].DefaultLength = sizeof(ULONG);
|
Parameters[7].DefaultLength = 0;
|
||||||
|
|
||||||
Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[8].Name = L"KeyboardDataQueueSize";
|
Parameters[8].Name = L"PollStatusIterations";
|
||||||
Parameters[8].EntryContext =
|
Parameters[8].EntryContext = &Settings->PollStatusIterations;
|
||||||
&DevExt->KeyboardAttributes.InputDataQueueLength;
|
|
||||||
Parameters[8].DefaultType = REG_DWORD;
|
Parameters[8].DefaultType = REG_DWORD;
|
||||||
Parameters[8].DefaultData = &DefaultKeyboardDataQueueSize;
|
Parameters[8].DefaultData = &DefaultPollStatusIterations;
|
||||||
Parameters[8].DefaultLength = sizeof(ULONG);
|
Parameters[8].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[9].Name = L"OverrideKeyboardType";
|
Parameters[9].Name = L"OverrideKeyboardType";
|
||||||
Parameters[9].EntryContext = &DevExt->Settings.OverrideKeyboardType;
|
Parameters[9].EntryContext = &Settings->OverrideKeyboardType;
|
||||||
Parameters[9].DefaultType = REG_DWORD;
|
Parameters[9].DefaultType = REG_DWORD;
|
||||||
Parameters[9].DefaultData = &DefaultOverrideKeyboardType;
|
Parameters[9].DefaultData = &DefaultOverrideKeyboardType;
|
||||||
Parameters[9].DefaultLength = sizeof(ULONG);
|
Parameters[9].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[10].Name = L"OverrideKeyboardSubtype";
|
Parameters[10].Name = L"OverrideKeyboardSubtype";
|
||||||
Parameters[10].EntryContext = &DevExt->Settings.OverrideKeyboardSubtype;
|
Parameters[10].EntryContext = &Settings->OverrideKeyboardSubtype;
|
||||||
Parameters[10].DefaultType = REG_DWORD;
|
Parameters[10].DefaultType = REG_DWORD;
|
||||||
Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype;
|
Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype;
|
||||||
Parameters[10].DefaultLength = sizeof(ULONG);
|
Parameters[10].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[11].Name = L"MouseDataQueueSize";
|
Parameters[11].Name = L"PollingIterations";
|
||||||
Parameters[11].EntryContext =
|
Parameters[11].EntryContext = &Settings->PollingIterations;
|
||||||
&DevExt->MouseAttributes.InputDataQueueLength;
|
|
||||||
Parameters[11].DefaultType = REG_DWORD;
|
Parameters[11].DefaultType = REG_DWORD;
|
||||||
Parameters[11].DefaultData = &DefaultMouseDataQueueSize;
|
Parameters[11].DefaultData = &DefaultPollingIterations;
|
||||||
Parameters[11].DefaultLength = sizeof(ULONG);
|
Parameters[11].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[12].Name = L"MouseResendStallTime";
|
Parameters[12].Name = L"PollingIterationsMaximum";
|
||||||
Parameters[12].EntryContext = &DevExt->Settings.MouseResendStallTime;
|
Parameters[12].EntryContext = &Settings->PollingIterationsMaximum;
|
||||||
Parameters[12].DefaultType = REG_DWORD;
|
Parameters[12].DefaultType = REG_DWORD;
|
||||||
Parameters[12].DefaultData = &DefaultMouseResendStallTime;
|
Parameters[12].DefaultData = &DefaultPollingIterationsMaximum;
|
||||||
Parameters[12].DefaultLength = sizeof(ULONG);
|
Parameters[12].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[13].Name = L"MouseSynchIn100ns";
|
Parameters[13].Name = L"ResendIterations";
|
||||||
Parameters[13].EntryContext = &DevExt->Settings.MouseSynchIn100ns;
|
Parameters[13].EntryContext = &Settings->ResendIterations;
|
||||||
Parameters[13].DefaultType = REG_DWORD;
|
Parameters[13].DefaultType = REG_DWORD;
|
||||||
Parameters[13].DefaultData = &DefaultMouseSynchIn100ns;
|
Parameters[13].DefaultData = &DefaultResendIterations;
|
||||||
Parameters[13].DefaultLength = sizeof(ULONG);
|
Parameters[13].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[14].Name = L"MouseResolution";
|
Parameters[14].Name = L"SampleRate";
|
||||||
Parameters[14].EntryContext = &DevExt->Settings.MouseResolution;
|
Parameters[14].EntryContext = &Settings->SampleRate;
|
||||||
Parameters[14].DefaultType = REG_DWORD;
|
Parameters[14].DefaultType = REG_DWORD;
|
||||||
Parameters[14].DefaultData = &DefaultMouseResolution;
|
Parameters[14].DefaultData = &DefaultSampleRate;
|
||||||
Parameters[14].DefaultLength = sizeof(ULONG);
|
Parameters[14].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
Parameters[15].Name = L"SampleRate";
|
Parameters[15].Name = L"CrashOnCtrlScroll";
|
||||||
Parameters[15].EntryContext = &DevExt->MouseAttributes.SampleRate;
|
Parameters[15].EntryContext = &Settings->CrashOnCtrlScroll;
|
||||||
Parameters[15].DefaultType = REG_DWORD;
|
Parameters[15].DefaultType = REG_DWORD;
|
||||||
Parameters[15].DefaultData = &DefaultSampleRate;
|
Parameters[15].DefaultData = &DefaultCrashOnCtrlScroll;
|
||||||
Parameters[15].DefaultLength = sizeof(ULONG);
|
Parameters[15].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
Parameters[16].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Status = RtlQueryRegistryValues(
|
||||||
Parameters[16].Name = L"NumberOfButtons";
|
RTL_REGISTRY_ABSOLUTE,
|
||||||
Parameters[16].EntryContext = &DevExt->Settings.NumberOfButtons;
|
RegistryPath->Buffer,
|
||||||
Parameters[16].DefaultType = REG_DWORD;
|
Parameters,
|
||||||
Parameters[16].DefaultData = &DefaultNumberOfButtons;
|
NULL,
|
||||||
Parameters[16].DefaultLength = sizeof(ULONG);
|
NULL);
|
||||||
|
|
||||||
Parameters[17].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
if (NT_SUCCESS(Status))
|
||||||
Parameters[17].Name = L"EnableWheelDetection";
|
{
|
||||||
Parameters[17].EntryContext = &DevExt->Settings.EnableWheelDetection;
|
/* Check values */
|
||||||
Parameters[17].DefaultType = REG_DWORD;
|
if (Settings->KeyboardDataQueueSize < 1)
|
||||||
Parameters[17].DefaultData = &DefaultEnableWheelDetection;
|
Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize;
|
||||||
Parameters[17].DefaultLength = sizeof(ULONG);
|
if (Settings->MouseDataQueueSize < 1)
|
||||||
|
Settings->MouseDataQueueSize = DefaultMouseDataQueueSize;
|
||||||
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
|
if (Settings->NumberOfButtons < 1)
|
||||||
I8042RegistryPath.Buffer,
|
Settings->NumberOfButtons = DefaultNumberOfButtons;
|
||||||
Parameters,
|
if (Settings->PollingIterations < 0x400)
|
||||||
NULL,
|
Settings->PollingIterations = DefaultPollingIterations;
|
||||||
NULL);
|
if (Settings->PollingIterationsMaximum < 0x400)
|
||||||
|
Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum;
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (Settings->ResendIterations < 1)
|
||||||
/* Actually, the defaults are not set when the function
|
Settings->ResendIterations = DefaultResendIterations;
|
||||||
* fails, as would happen during setup, so you have to
|
}
|
||||||
* set them manually anyway...
|
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||||
*/
|
{
|
||||||
RTL_QUERY_REGISTRY_TABLE *Current = Parameters;
|
/* Registry path doesn't exist. Set defaults */
|
||||||
DPRINT ("Can't read registry: %x\n", Status);
|
Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize;
|
||||||
while (Current->Name) {
|
Settings->MouseDataQueueSize = DefaultMouseDataQueueSize;
|
||||||
*((PULONG)Current->EntryContext) =
|
Settings->MouseResolution = DefaultMouseResolution;
|
||||||
*((PULONG)Current->DefaultData);
|
Settings->MouseSynchIn100ns = DefaultMouseSynchIn100ns;
|
||||||
Current++;
|
Settings->NumberOfButtons = DefaultNumberOfButtons;
|
||||||
|
Settings->PollStatusIterations = DefaultPollStatusIterations;
|
||||||
|
Settings->OverrideKeyboardType = DefaultOverrideKeyboardType;
|
||||||
|
Settings->OverrideKeyboardSubtype = DefaultOverrideKeyboardSubtype;
|
||||||
|
Settings->PollingIterations = DefaultPollingIterations;
|
||||||
|
Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum;
|
||||||
|
Settings->ResendIterations = DefaultResendIterations;
|
||||||
|
Settings->SampleRate = DefaultSampleRate;
|
||||||
|
Settings->CrashOnCtrlScroll = DefaultCrashOnCtrlScroll;
|
||||||
|
if (!RtlCreateUnicodeString(&Settings->KeyboardDeviceBaseName, DefaultKeyboardDeviceBaseName)
|
||||||
|
|| !RtlCreateUnicodeString(&Settings->PointerDeviceBaseName, DefaultPointerDeviceBaseName))
|
||||||
|
{
|
||||||
|
DPRINT("RtlCreateUnicodeString() failed\n");
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
DPRINT ("Manually set defaults\n");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DevExt->Settings.MouseResolution > 3)
|
if (NT_SUCCESS(Status))
|
||||||
DevExt->Settings.MouseResolution = 3;
|
{
|
||||||
|
DPRINT("KeyboardDataQueueSize : 0x%lx\n", Settings->KeyboardDataQueueSize);
|
||||||
|
DPRINT("KeyboardDeviceBaseName : %wZ\n", &Settings->KeyboardDeviceBaseName);
|
||||||
|
DPRINT("MouseDataQueueSize : 0x%lx\n", Settings->MouseDataQueueSize);
|
||||||
|
DPRINT("MouseResolution : 0x%lx\n", Settings->MouseResolution);
|
||||||
|
DPRINT("MouseSynchIn100ns : %lu\n", Settings->MouseSynchIn100ns);
|
||||||
|
DPRINT("NumberOfButtons : 0x%lx\n", Settings->NumberOfButtons);
|
||||||
|
DPRINT("PointerDeviceBaseName : %wZ\n", &Settings->PointerDeviceBaseName);
|
||||||
|
DPRINT("PollStatusIterations : 0x%lx\n", Settings->PollStatusIterations);
|
||||||
|
DPRINT("OverrideKeyboardType : 0x%lx\n", Settings->OverrideKeyboardType);
|
||||||
|
DPRINT("OverrideKeyboardSubtype : 0x%lx\n", Settings->OverrideKeyboardSubtype);
|
||||||
|
DPRINT("PollingIterations : 0x%lx\n", Settings->PollingIterations);
|
||||||
|
DPRINT("PollingIterationsMaximum : %lu\n", Settings->PollingIterationsMaximum);
|
||||||
|
DPRINT("ResendIterations : 0x%lx\n", Settings->ResendIterations);
|
||||||
|
DPRINT("SampleRate : %lu\n", Settings->SampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("Done reading registry\n");
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
273
reactos/drivers/input/i8042prt/setup.c
Normal file
273
reactos/drivers/input/i8042prt/setup.c
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/input/i8042prt/setup.c
|
||||||
|
* PURPOSE: Create a legacy PDO during ReactOS installation
|
||||||
|
* PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* NOTE:
|
||||||
|
* All this file is a big hack and should be removed one day...
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
#define KEYBOARD_DATA_PORT 0x60
|
||||||
|
#define KEYBOARD_CONTROL_PORT 0x64
|
||||||
|
#define KEYBOARD_IRQ 1
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
IsFirstStageSetup(
|
||||||
|
VOID)
|
||||||
|
{
|
||||||
|
UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\Setup");
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
HANDLE hSetupKey = (HANDLE)NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
BOOLEAN ret = TRUE;
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
Status = ZwOpenKey(&hSetupKey, KEY_QUERY_VALUE, &ObjectAttributes);
|
||||||
|
|
||||||
|
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||||
|
ret = TRUE;
|
||||||
|
else
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
if (hSetupKey != (HANDLE)NULL)
|
||||||
|
ZwClose(hSetupKey);
|
||||||
|
DPRINT("IsFirstStageSetup() returns %s\n", ret ? "YES" : "NO");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID NTAPI
|
||||||
|
SendStartDevice(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PVOID Context,
|
||||||
|
IN ULONG Count)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT Pdo;
|
||||||
|
PCM_RESOURCE_LIST AllocatedResources = NULL;
|
||||||
|
PCM_RESOURCE_LIST AllocatedResourcesTranslated = NULL;
|
||||||
|
PDEVICE_OBJECT TopDeviceObject = NULL;
|
||||||
|
KEVENT Event;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
ULONG ResourceListSize;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Pdo = (PDEVICE_OBJECT)Context;
|
||||||
|
DPRINT("SendStartDevice(%p)\n", Pdo);
|
||||||
|
|
||||||
|
/* Create default resource list */
|
||||||
|
ResourceListSize = sizeof(CM_RESOURCE_LIST) + 3 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||||||
|
AllocatedResources = ExAllocatePoolWithTag(PagedPool, ResourceListSize, I8042PRT_TAG);
|
||||||
|
if (!AllocatedResources)
|
||||||
|
{
|
||||||
|
DPRINT("ExAllocatePoolWithTag() failed\n");
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
AllocatedResources->Count = 1;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.Version = 1;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.Revision = 1;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.Count = 3;
|
||||||
|
/* Data port */
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypePort;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].Flags = 0; /* FIXME */
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start.u.HighPart = 0;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start.u.LowPart = KEYBOARD_DATA_PORT;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length = 1;
|
||||||
|
/* Control port */
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].Type = CmResourceTypePort;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].Flags = 0; /* FIXME */
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].u.Port.Start.u.HighPart = 0;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].u.Port.Start.u.LowPart = KEYBOARD_CONTROL_PORT;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].u.Port.Length = 1;
|
||||||
|
/* Interrupt */
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].Type = CmResourceTypeInterrupt;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level = KEYBOARD_IRQ;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector = 0;
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Affinity = (KAFFINITY)-1;
|
||||||
|
|
||||||
|
/* Create default resource list translated */
|
||||||
|
AllocatedResourcesTranslated = ExAllocatePoolWithTag(PagedPool, ResourceListSize, I8042PRT_TAG);
|
||||||
|
if (!AllocatedResourcesTranslated)
|
||||||
|
{
|
||||||
|
DPRINT("ExAllocatePoolWithTag() failed\n");
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
RtlCopyMemory(AllocatedResourcesTranslated, AllocatedResources, ResourceListSize);
|
||||||
|
AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector = HalGetInterruptVector(
|
||||||
|
Internal, 0,
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level,
|
||||||
|
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector,
|
||||||
|
(PKIRQL)&AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level,
|
||||||
|
&AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Affinity);
|
||||||
|
|
||||||
|
/* Send IRP_MN_START_DEVICE */
|
||||||
|
TopDeviceObject = IoGetAttachedDeviceReference(Pdo);
|
||||||
|
KeInitializeEvent(
|
||||||
|
&Event,
|
||||||
|
NotificationEvent,
|
||||||
|
FALSE);
|
||||||
|
Irp = IoBuildSynchronousFsdRequest(
|
||||||
|
IRP_MJ_PNP,
|
||||||
|
TopDeviceObject,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
&Event,
|
||||||
|
&IoStatusBlock);
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Stack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
Stack->MinorFunction = IRP_MN_START_DEVICE;
|
||||||
|
Stack->Parameters.StartDevice.AllocatedResources = AllocatedResources;
|
||||||
|
Stack->Parameters.StartDevice.AllocatedResourcesTranslated = AllocatedResourcesTranslated;
|
||||||
|
Status = IoCallDriver(TopDeviceObject, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(
|
||||||
|
&Event,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = IoStatusBlock.Status;
|
||||||
|
}
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoCallDriver() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (TopDeviceObject)
|
||||||
|
ObDereferenceObject(TopDeviceObject);
|
||||||
|
if (AllocatedResources)
|
||||||
|
ExFreePoolWithTag(AllocatedResources, I8042PRT_TAG);
|
||||||
|
if (AllocatedResourcesTranslated)
|
||||||
|
ExFreePoolWithTag(AllocatedResourcesTranslated, I8042PRT_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
AddRegistryEntry(
|
||||||
|
IN PCWSTR PortTypeName,
|
||||||
|
IN PUNICODE_STRING DeviceName,
|
||||||
|
IN PCWSTR RegistryPath)
|
||||||
|
{
|
||||||
|
UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
HANDLE hDeviceMapKey = (HANDLE)-1;
|
||||||
|
HANDLE hPortKey = (HANDLE)-1;
|
||||||
|
UNICODE_STRING PortTypeNameU;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&PortTypeNameU, PortTypeName);
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL);
|
||||||
|
Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (hDeviceMapKey != (HANDLE)-1)
|
||||||
|
ZwClose(hDeviceMapKey);
|
||||||
|
if (hPortKey != (HANDLE)-1)
|
||||||
|
ZwClose(hPortKey);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
i8042AddLegacyKeyboard(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath)
|
||||||
|
{
|
||||||
|
UNICODE_STRING KeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPort8042");
|
||||||
|
PI8042_DEVICE_TYPE DeviceExtension = NULL;
|
||||||
|
PDEVICE_OBJECT Pdo = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("i8042AddLegacyKeyboard()\n");
|
||||||
|
|
||||||
|
/* Create a named PDO */
|
||||||
|
Status = IoCreateDevice(
|
||||||
|
DriverObject,
|
||||||
|
sizeof(I8042_DEVICE_TYPE),
|
||||||
|
&KeyboardName,
|
||||||
|
FILE_DEVICE_8042_PORT,
|
||||||
|
FILE_DEVICE_SECURE_OPEN,
|
||||||
|
TRUE,
|
||||||
|
&Pdo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize device extension */
|
||||||
|
DeviceExtension = (PI8042_DEVICE_TYPE)Pdo->DeviceExtension;
|
||||||
|
RtlZeroMemory(DeviceExtension, sizeof(I8042_DEVICE_TYPE));
|
||||||
|
*DeviceExtension = PhysicalDeviceObject;
|
||||||
|
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
/* Add FDO at the top of the PDO */
|
||||||
|
Status = i8042AddDevice(DriverObject, Pdo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("i8042AddDevice() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We will send the IRP_MN_START_DEVICE later, once kbdclass is loaded */
|
||||||
|
AddRegistryEntry(L"KeyboardPort", &KeyboardName, RegistryPath->Buffer);
|
||||||
|
IoRegisterBootDriverReinitialization(
|
||||||
|
DriverObject,
|
||||||
|
SendStartDevice,
|
||||||
|
Pdo);
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
/* Yes, completly forget the Pdo pointer, as we will never
|
||||||
|
* have to unload this driver during first stage setup.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
if (Pdo)
|
||||||
|
IoDeleteDevice(Pdo);
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue