mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +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:
|
||||
|
||||
createclose.c: open/close devices functionnality
|
||||
|
||||
i8042prt.c: Main controller functionality, things shared by keyboards and mice
|
||||
|
||||
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
|
||||
standard ps2 and microsoft mice
|
||||
|
||||
pnp.c: Plug&Play functionnality
|
||||
|
||||
ps2pp.c: logitech ps2++ mouse packat parsing (basic)
|
||||
|
||||
readwrite.c: read/write to the i8042 controller
|
||||
|
||||
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
|
||||
|
@ -33,7 +43,6 @@ Things to add:
|
|||
- General robustness: reset mouse if things go wrong
|
||||
- Handling all registry settings
|
||||
- ACPI
|
||||
- Make it work more like a WDM driver
|
||||
|
||||
Things not to add:
|
||||
|
||||
|
@ -49,18 +58,6 @@ Things requiring work elsewhere:
|
|||
hardcoded cases, this should not be hard to fix.
|
||||
|
||||
- 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
|
||||
at a time (kbdclass should, mouclass does not). Win32k should send such
|
||||
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
|
||||
#define _I8042DRV_H
|
||||
#ifndef _I8042PRT_H_
|
||||
#define _I8042PRT_H_
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <ntifs.h>
|
||||
#include <kbdmou.h>
|
||||
#include <ntdd8042.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STDCALL
|
||||
#define DDKAPI
|
||||
#endif
|
||||
|
||||
#define KEYBOARD_IRQ 1
|
||||
#define MOUSE_IRQ 12
|
||||
#define KBD_BUFFER_SIZE 32
|
||||
|
||||
#define WHEEL_DELTA 120
|
||||
#include <ntddkbd.h>
|
||||
#include <bugcodes.h>
|
||||
#include <poclass.h>
|
||||
#include <kdfuncs.h>
|
||||
#include <debug.h>
|
||||
|
||||
/*-----------------------------------------------------
|
||||
* 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;
|
||||
int CurInput;
|
||||
UCHAR * Input;
|
||||
int NumOutput;
|
||||
int CurOutput;
|
||||
UCHAR * Output;
|
||||
NTSTATUS Status;
|
||||
dsStopped,
|
||||
dsStarted,
|
||||
dsPaused,
|
||||
dsRemoved,
|
||||
dsSurpriseRemoved
|
||||
} DEVICE_STATE;
|
||||
|
||||
BOOLEAN GotAck;
|
||||
KEVENT Event;
|
||||
|
||||
PVOID DevExt;
|
||||
} COMMAND_CONTEXT, *PCOMMAND_CONTEXT;
|
||||
typedef struct _I8042_SETTINGS
|
||||
{
|
||||
/* Registry settings */
|
||||
ULONG KeyboardDataQueueSize; /* done */
|
||||
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
|
||||
{
|
||||
|
@ -42,108 +53,47 @@ typedef enum _MOUSE_TIMEOUT_STATE
|
|||
TimeoutCancel
|
||||
} MOUSE_TIMEOUT_STATE, *PMOUSE_TIMEOUT_STATE;
|
||||
|
||||
/* TODO: part of this should be in the _ATTRIBUTES structs instead */
|
||||
typedef struct _I8042_SETTINGS
|
||||
typedef struct _INTERRUPT_DATA
|
||||
{
|
||||
ULONG Headless; /* done */
|
||||
ULONG CrashScroll;
|
||||
ULONG CrashSysRq; /* done */
|
||||
ULONG ReportResetErrors;
|
||||
ULONG PollStatusIterations; /* done */
|
||||
ULONG ResendIterations; /* done */
|
||||
ULONG PollingIterations;
|
||||
ULONG PollingIterationsMaximum;
|
||||
ULONG OverrideKeyboardType;
|
||||
ULONG OverrideKeyboardSubtype;
|
||||
ULONG MouseResendStallTime;
|
||||
ULONG MouseSynchIn100ns; /* done */
|
||||
ULONG MouseResolution; /* done */
|
||||
ULONG NumberOfButtons;
|
||||
ULONG EnableWheelDetection;
|
||||
} I8042_SETTINGS, *PI8042_SETTINGS;
|
||||
PKINTERRUPT Object;
|
||||
ULONG Vector;
|
||||
KIRQL Dirql;
|
||||
KINTERRUPT_MODE InterruptMode;
|
||||
BOOLEAN ShareInterrupt;
|
||||
KAFFINITY Affinity;
|
||||
} INTERRUPT_DATA, *PINTERRUPT_DATA;
|
||||
|
||||
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,
|
||||
Intellimouse,
|
||||
IntellimouseExplorer,
|
||||
Ps2pp
|
||||
} I8042_MOUSE_TYPE, *PI8042_MOUSE_TYPE;
|
||||
PUCHAR DataPort; /* Usually 0x60 */
|
||||
PUCHAR ControlPort; /* Usually 0x64 */
|
||||
I8042_SETTINGS Settings;
|
||||
ULONG Flags;
|
||||
|
||||
typedef enum _I8042_DEVICE_TYPE
|
||||
{
|
||||
Keyboard,
|
||||
Mouse
|
||||
} 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;
|
||||
PI8042_KEYBOARD_EXTENSION KeyboardExtension;
|
||||
INTERRUPT_DATA KeyboardInterrupt;
|
||||
PI8042_MOUSE_EXTENSION MouseExtension;
|
||||
INTERRUPT_DATA MouseInterrupt;
|
||||
PKINTERRUPT HighestDIRQLInterrupt;
|
||||
KSPIN_LOCK SpinLock;
|
||||
KDPC DpcKbd;
|
||||
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;
|
||||
KIRQL HighestDirql;
|
||||
|
||||
OUTPUT_PACKET Packet;
|
||||
ULONG PacketResends;
|
||||
|
@ -154,228 +104,351 @@ typedef struct _DEVICE_EXTENSION
|
|||
|
||||
PIRP CurrentIrp;
|
||||
PDEVICE_OBJECT CurrentIrpDevice;
|
||||
} PORT_DEVICE_EXTENSION, *PPORT_DEVICE_EXTENSION;
|
||||
|
||||
/* registry config values */
|
||||
I8042_SETTINGS Settings;
|
||||
typedef struct _I8042_DRIVER_EXTENSION
|
||||
{
|
||||
UNICODE_STRING RegistryPath;
|
||||
|
||||
/* Debugger stuff */
|
||||
BOOLEAN TabPressed;
|
||||
ULONG DebugKey;
|
||||
PIO_WORKITEM DebugWorkItem;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
PORT_DEVICE_EXTENSION Port;
|
||||
LIST_ENTRY DeviceListHead;
|
||||
KSPIN_LOCK DeviceListLock;
|
||||
} I8042_DRIVER_EXTENSION, *PI8042_DRIVER_EXTENSION;
|
||||
|
||||
typedef enum _I8042_DEVICE_TYPE
|
||||
{
|
||||
Unknown,
|
||||
Keyboard,
|
||||
Mouse,
|
||||
PhysicalDeviceObject
|
||||
} I8042_DEVICE_TYPE, *PI8042_DEVICE_TYPE;
|
||||
|
||||
typedef struct _FDO_DEVICE_EXTENSION
|
||||
{
|
||||
PDEVICE_EXTENSION PortDevExt;
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
PIO_WORKITEM WorkItem;
|
||||
PDEVICE_OBJECT Target;
|
||||
PIRP Irp;
|
||||
} I8042_HOOK_WORKITEM, *PI8042_HOOK_WORKITEM;
|
||||
|
||||
/*
|
||||
/*-----------------------------------------------------
|
||||
* 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 CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
|
||||
#define KEYBOARD_POWER_CODE 0x5E
|
||||
#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
|
||||
*/
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define KBD_READ_MODE 0x20
|
||||
#define KBD_WRITE_MODE 0x60
|
||||
#define KBD_SELF_TEST 0xAA
|
||||
#define KBD_LINE_TEST 0xAB
|
||||
#define KBD_CTRL_ENABLE 0xAE
|
||||
|
||||
#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
|
||||
*/
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define KBD_SET_LEDS 0xED
|
||||
#define KBD_GET_ID 0xF2
|
||||
#define KBD_ENABLE 0xF4
|
||||
#define KBD_DISABLE 0xF5
|
||||
#define KBD_RESET 0xFF
|
||||
#define KBD_CMD_SET_LEDS 0xED
|
||||
#define KBD_CMD_GET_ID 0xF2
|
||||
|
||||
/*-----------------------------------------------------
|
||||
* Keyboard responses
|
||||
* --------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Keyboard responces
|
||||
*/
|
||||
|
||||
#define KBD_BATCC 0xAA
|
||||
#define KBD_ACK 0xFA
|
||||
#define KBD_NACK 0xFC
|
||||
#define KBD_RESEND 0xFE
|
||||
|
||||
/*
|
||||
/*-----------------------------------------------------
|
||||
* Controller status register bits
|
||||
*/
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define KBD_OBF 0x01
|
||||
#define KBD_IBF 0x02
|
||||
#define KBD_AUX 0x10
|
||||
#define KBD_GTO 0x40
|
||||
#define MOU_OBF 0x20
|
||||
#define KBD_PERR 0x80
|
||||
|
||||
/*
|
||||
/*-----------------------------------------------------
|
||||
* Controller command byte bits
|
||||
*/
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define CCB_KBD_INT_ENAB 0x01
|
||||
#define CCB_MOUSE_INT_ENAB 0x02
|
||||
#define CCB_SYSTEM_FLAG 0x04
|
||||
#define CCB_IGN_KEY_LOCK 0x08
|
||||
#define CCB_KBD_DISAB 0x10
|
||||
#define CCB_MOUSE_DISAB 0x20
|
||||
#define CCB_TRANSLATE 0x40
|
||||
|
||||
|
||||
/*
|
||||
/*-----------------------------------------------------
|
||||
* LED bits
|
||||
*/
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define KBD_LED_SCROLL 0x01
|
||||
#define KBD_LED_NUM 0x02
|
||||
#define KBD_LED_CAPS 0x04
|
||||
|
||||
/*
|
||||
/*-----------------------------------------------------
|
||||
* Mouse commands
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define MOU_CMD_GET_ID 0xF2
|
||||
#define MOU_CMD_RESET 0xFF
|
||||
|
||||
/*-----------------------------------------------------
|
||||
* Mouse responses
|
||||
*/
|
||||
* --------------------------------------------------*/
|
||||
|
||||
#define MOUSE_ACK 0xFA
|
||||
#define MOUSE_ERROR 0xFC
|
||||
#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,
|
||||
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);
|
||||
DRIVER_DISPATCH i8042Close;
|
||||
|
||||
/* keyboard.c */
|
||||
VOID STDCALL I8042IsrWritePortKbd(PVOID Context,
|
||||
UCHAR Value);
|
||||
|
||||
NTSTATUS STDCALL I8042SynchWritePortKbd(PVOID Context,
|
||||
UCHAR Value,
|
||||
BOOLEAN WaitForAck);
|
||||
NTSTATUS DDKAPI
|
||||
i8042SynchWritePortKbd(
|
||||
IN PVOID Context,
|
||||
IN UCHAR Value,
|
||||
IN BOOLEAN WaitForAck);
|
||||
|
||||
KSERVICE_ROUTINE I8042InterruptServiceKbd;
|
||||
BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt,
|
||||
VOID * Context);
|
||||
DRIVER_STARTIO i8042KbdStartIo;
|
||||
|
||||
VOID STDCALL I8042DpcRoutineKbd(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2);
|
||||
DRIVER_DISPATCH i8042KbdDeviceControl;
|
||||
|
||||
BOOLEAN STDCALL I8042StartIoKbd(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
DRIVER_DISPATCH i8042KbdInternalDeviceControl;
|
||||
|
||||
NTSTATUS STDCALL I8042InternalDeviceControlKbd(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp);
|
||||
KSERVICE_ROUTINE i8042KbdInterruptService;
|
||||
|
||||
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 */
|
||||
VOID STDCALL I8042ReadRegistry(PDRIVER_OBJECT DriverObject,
|
||||
PDEVICE_EXTENSION DevExt);
|
||||
NTSTATUS
|
||||
i8042StartPacket(
|
||||
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 */
|
||||
VOID STDCALL I8042DpcRoutineMouse(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2);
|
||||
|
||||
VOID STDCALL I8042DpcRoutineMouseTimeout(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2);
|
||||
VOID
|
||||
i8042MouHandle(
|
||||
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||
IN UCHAR Output);
|
||||
|
||||
KSERVICE_ROUTINE I8042InterruptServiceMouse;
|
||||
BOOLEAN STDCALL I8042InterruptServiceMouse(struct _KINTERRUPT *Interrupt,
|
||||
VOID *Context);
|
||||
VOID
|
||||
i8042MouHandleButtons(
|
||||
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||
IN USHORT Mask);
|
||||
|
||||
NTSTATUS STDCALL I8042InternalDeviceControlMouse(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp);
|
||||
NTSTATUS
|
||||
i8042MouInitialize(
|
||||
IN PI8042_MOUSE_EXTENSION DeviceExtension);
|
||||
|
||||
VOID STDCALL I8042QueueMousePacket(PVOID Context);
|
||||
DRIVER_DISPATCH i8042MouInternalDeviceControl;
|
||||
|
||||
VOID STDCALL I8042MouseHandleButtons(PDEVICE_EXTENSION DevExt,
|
||||
USHORT Mask);
|
||||
KSERVICE_ROUTINE i8042MouInterruptService;
|
||||
|
||||
VOID STDCALL I8042MouseHandle(PDEVICE_EXTENSION DevExt,
|
||||
UCHAR Output);
|
||||
/* pnp.c */
|
||||
|
||||
BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt);
|
||||
BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt);
|
||||
BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt);
|
||||
BOOLEAN
|
||||
i8042ChangeMode(
|
||||
IN PPORT_DEVICE_EXTENSION DeviceExtension,
|
||||
IN UCHAR FlagsToDisable,
|
||||
IN UCHAR FlagsToEnable);
|
||||
|
||||
DRIVER_DISPATCH i8042Pnp;
|
||||
|
||||
/* 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">
|
||||
<module name="i8042prt" type="kernelmodedriver" installbase="system32/drivers" installname="i8042prt.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)" />
|
||||
<include base="i8042prt">.</include>
|
||||
<define name="NDEBUG" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<file>createclose.c</file>
|
||||
<file>i8042prt.c</file>
|
||||
<file>keyboard.c</file>
|
||||
<file>misc.c</file>
|
||||
<file>mouse.c</file>
|
||||
<file>pnp.c</file>
|
||||
<file>ps2pp.c</file>
|
||||
<file>readwrite.c</file>
|
||||
<file>registry.c</file>
|
||||
<file>setup.c</file>
|
||||
<file>i8042prt.rc</file>
|
||||
</module>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#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_ORIGINAL_FILENAME "i8042prt.sys\0"
|
||||
#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 kernel
|
||||
* FILE: drivers/input/i8042prt/ps2pp.c
|
||||
* PURPOSE: i8042prt driver
|
||||
* ps2pp protocol handling
|
||||
* PROGRAMMER: Tinus
|
||||
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/input/i8042prt/ps2pp.c
|
||||
* PURPOSE: ps2pp protocol handling
|
||||
* PROGRAMMERS: Copyright Martijn Vernooij (o112w8r02@sneakemail.com)
|
||||
* Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#include "i8042prt.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
#include <debug.h>
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input)
|
||||
VOID
|
||||
i8042MouHandlePs2pp(
|
||||
IN PI8042_MOUSE_EXTENSION DeviceExtension,
|
||||
IN UCHAR Input)
|
||||
{
|
||||
UCHAR PktType;
|
||||
PMOUSE_INPUT_DATA MouseInput = DevExt->MouseBuffer +
|
||||
DevExt->MouseInBuffer;
|
||||
PMOUSE_INPUT_DATA MouseInput;
|
||||
|
||||
/* First, collect 3 bytes for a packet
|
||||
* 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
|
||||
*/
|
||||
MouseInput = DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer;
|
||||
|
||||
switch (DevExt->MouseState) {
|
||||
case MouseIdle:
|
||||
case XMovement:
|
||||
DevExt->MouseLogiBuffer[DevExt->MouseState] = Input;
|
||||
DevExt->MouseState++;
|
||||
break;
|
||||
/* First, collect 3 bytes for a packet
|
||||
* 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
|
||||
*/
|
||||
|
||||
case YMovement:
|
||||
DevExt->MouseLogiBuffer[2] = Input;
|
||||
DevExt->MouseState = MouseIdle;
|
||||
switch (DeviceExtension->MouseState)
|
||||
{
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
/* first check if it's a normal packet */
|
||||
|
||||
/* sanity check */
|
||||
|
||||
if (((DevExt->MouseLogiBuffer[0] & 0x48) != 0x48) ||
|
||||
(((DevExt->MouseLogiBuffer[1] & 0x0C) >> 2) !=
|
||||
(DevExt->MouseLogiBuffer[2] & 0x03))) {
|
||||
DPRINT1("Ps2pp packet fails sanity checks\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now get the packet type */
|
||||
|
||||
PktType = ((DevExt->MouseLogiBuffer[0] & 0x30) >> 4) &
|
||||
((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;
|
||||
if (!(DeviceExtension->MouseLogiBuffer[0] & 0xC0))
|
||||
{
|
||||
DeviceExtension->MouseState = MouseIdle;
|
||||
i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[0]);
|
||||
i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[1]);
|
||||
i8042MouHandle(DeviceExtension, DeviceExtension->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;
|
||||
}
|
||||
I8042MouseHandleButtons(DevExt, MOUSE_BUTTON_4_DOWN |
|
||||
MOUSE_BUTTON_5_DOWN);
|
||||
I8042QueueMousePacket(
|
||||
DevExt->MouseObject);
|
||||
return;
|
||||
|
||||
/* sanity check */
|
||||
if (((DeviceExtension->MouseLogiBuffer[0] & 0x48) != 0x48) ||
|
||||
(((DeviceExtension->MouseLogiBuffer[1] & 0x0C) >> 2) !=
|
||||
(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:
|
||||
/* These are for things that would probably
|
||||
* be handled by logitechs own driver.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
default:
|
||||
DPRINT1("Unexpected input state for ps2pp!\n");
|
||||
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 kernel
|
||||
* FILE: drivers/input/i8042prt/registry.c
|
||||
* PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver
|
||||
* Reading the registry
|
||||
* PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
|
||||
* Jason Filby (jasonfilby@yahoo.com)
|
||||
* Tinus
|
||||
* PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/input/i8042prt/i8042prt.c
|
||||
* PURPOSE: Reading the registry
|
||||
* 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 ****************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "i8042prt.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
* Read the registry keys associated with this device. The RegistryPath
|
||||
* var is a hack. This should be more like what microsoft does, but I
|
||||
* don't know exactly what they do except that it's a hack too...
|
||||
*/
|
||||
VOID STDCALL I8042ReadRegistry(PDRIVER_OBJECT DriverObject,
|
||||
PDEVICE_EXTENSION DevExt)
|
||||
|
||||
NTSTATUS
|
||||
ReadRegistryEntries(
|
||||
IN PUNICODE_STRING RegistryPath,
|
||||
OUT PI8042_SETTINGS Settings)
|
||||
{
|
||||
RTL_QUERY_REGISTRY_TABLE Parameters[19];
|
||||
|
||||
RTL_QUERY_REGISTRY_TABLE Parameters[17];
|
||||
NTSTATUS Status;
|
||||
|
||||
ULONG DefaultHeadless = 0;
|
||||
ULONG DefaultCrashScroll = 0;
|
||||
ULONG DefaultCrashSysRq = 0;
|
||||
ULONG DefaultReportResetErrors = 0;
|
||||
ULONG DefaultKeyboardDataQueueSize = 0x64;
|
||||
PCWSTR DefaultKeyboardDeviceBaseName = L"KeyboardPort";
|
||||
ULONG DefaultMouseDataQueueSize = 0x64;
|
||||
ULONG DefaultMouseResolution = 3;
|
||||
ULONG DefaultMouseSynchIn100ns = 20000000;
|
||||
ULONG DefaultNumberOfButtons = 2;
|
||||
PCWSTR DefaultPointerDeviceBaseName = L"PointerPort";
|
||||
ULONG DefaultPollStatusIterations = 1;
|
||||
ULONG DefaultResendIterations = 3;
|
||||
ULONG DefaultOverrideKeyboardType = 4;
|
||||
ULONG DefaultOverrideKeyboardSubtype = 0;
|
||||
ULONG DefaultPollingIterations = 12000;
|
||||
ULONG DefaultPollingIterationsMaximum = 12000;
|
||||
ULONG DefaultKeyboardDataQueueSize = 100;
|
||||
ULONG DefaultOverrideKeyboardType = 0;
|
||||
ULONG DefaultOverrideKeyboardSubtype = 0;
|
||||
ULONG DefaultMouseDataQueueSize = 100;
|
||||
ULONG DefaultMouseResendStallTime = 1000;
|
||||
ULONG DefaultMouseSynchIn100ns = 20000000;
|
||||
ULONG DefaultMouseResolution = 3;
|
||||
ULONG DefaultResendIterations = 0x3;
|
||||
ULONG DefaultSampleRate = 60;
|
||||
ULONG DefaultNumberOfButtons = 2;
|
||||
ULONG DefaultEnableWheelDetection = 1;
|
||||
ULONG DefaultCrashOnCtrlScroll;
|
||||
|
||||
/* 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));
|
||||
|
||||
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[0].Name = L"Headless";
|
||||
Parameters[0].EntryContext = &DevExt->Settings.Headless;
|
||||
Parameters[0].DefaultType = REG_DWORD;
|
||||
Parameters[0].DefaultData = &DefaultHeadless;
|
||||
Parameters[0].DefaultLength = sizeof(ULONG);
|
||||
Parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
||||
Parameters[0].Name = L"Parameters";
|
||||
|
||||
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[1].Name = L"CrashOnCtrlScroll";
|
||||
Parameters[1].EntryContext = &DevExt->Settings.CrashScroll;
|
||||
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[1].Name = L"KeyboardDataQueueSize";
|
||||
Parameters[1].EntryContext = &Settings->KeyboardDataQueueSize;
|
||||
Parameters[1].DefaultType = REG_DWORD;
|
||||
Parameters[1].DefaultData = &DefaultCrashScroll;
|
||||
Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize;
|
||||
Parameters[1].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[2].Name = L"BreakOnSysRq";
|
||||
Parameters[2].EntryContext = &DevExt->Settings.CrashSysRq;
|
||||
Parameters[2].DefaultType = REG_DWORD;
|
||||
Parameters[2].DefaultData = &DefaultCrashSysRq;
|
||||
Parameters[2].DefaultLength = sizeof(ULONG);
|
||||
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[2].Name = L"KeyboardDeviceBaseName";
|
||||
Parameters[2].EntryContext = &Settings->KeyboardDeviceBaseName;
|
||||
Parameters[2].DefaultType = REG_SZ;
|
||||
Parameters[2].DefaultData = (PVOID)DefaultKeyboardDeviceBaseName;
|
||||
Parameters[2].DefaultLength = 0;
|
||||
|
||||
Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[3].Name = L"ReportResetErrors";
|
||||
Parameters[3].EntryContext = &DevExt->Settings.ReportResetErrors;
|
||||
Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[3].Name = L"MouseDataQueueSize";
|
||||
Parameters[3].EntryContext = &Settings->MouseDataQueueSize;
|
||||
Parameters[3].DefaultType = REG_DWORD;
|
||||
Parameters[3].DefaultData = &DefaultReportResetErrors;
|
||||
Parameters[3].DefaultData = &DefaultMouseDataQueueSize;
|
||||
Parameters[3].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[4].Name = L"PollStatusIterations";
|
||||
Parameters[4].EntryContext = &DevExt->Settings.PollStatusIterations;
|
||||
Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[4].Name = L"MouseResolution";
|
||||
Parameters[4].EntryContext = &Settings->MouseResolution;
|
||||
Parameters[4].DefaultType = REG_DWORD;
|
||||
Parameters[4].DefaultData = &DefaultPollStatusIterations;
|
||||
Parameters[4].DefaultData = &DefaultMouseResolution;
|
||||
Parameters[4].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[5].Name = L"ResendIterations";
|
||||
Parameters[5].EntryContext = &DevExt->Settings.ResendIterations;
|
||||
Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[5].Name = L"MouseSynchIn100ns";
|
||||
Parameters[5].EntryContext = &Settings->MouseSynchIn100ns;
|
||||
Parameters[5].DefaultType = REG_DWORD;
|
||||
Parameters[5].DefaultData = &DefaultResendIterations;
|
||||
Parameters[5].DefaultData = &DefaultMouseSynchIn100ns;
|
||||
Parameters[5].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[6].Name = L"PollingIterations";
|
||||
Parameters[6].EntryContext = &DevExt->Settings.PollingIterations;
|
||||
Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[6].Name = L"NumberOfButtons";
|
||||
Parameters[6].EntryContext = &Settings->NumberOfButtons;
|
||||
Parameters[6].DefaultType = REG_DWORD;
|
||||
Parameters[6].DefaultData = &DefaultPollingIterations;
|
||||
Parameters[6].DefaultData = &DefaultNumberOfButtons;
|
||||
Parameters[6].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[7].Name = L"PollingIterationsMaximum";
|
||||
Parameters[7].EntryContext = &DevExt->Settings.PollingIterationsMaximum;
|
||||
Parameters[7].DefaultType = REG_DWORD;
|
||||
Parameters[7].DefaultData = &DefaultPollingIterationsMaximum;
|
||||
Parameters[7].DefaultLength = sizeof(ULONG);
|
||||
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[7].Name = L"PointerDeviceBaseName";
|
||||
Parameters[7].EntryContext = &Settings->PointerDeviceBaseName;
|
||||
Parameters[7].DefaultType = REG_SZ;
|
||||
Parameters[7].DefaultData = (PVOID)DefaultPointerDeviceBaseName;
|
||||
Parameters[7].DefaultLength = 0;
|
||||
|
||||
Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[8].Name = L"KeyboardDataQueueSize";
|
||||
Parameters[8].EntryContext =
|
||||
&DevExt->KeyboardAttributes.InputDataQueueLength;
|
||||
Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[8].Name = L"PollStatusIterations";
|
||||
Parameters[8].EntryContext = &Settings->PollStatusIterations;
|
||||
Parameters[8].DefaultType = REG_DWORD;
|
||||
Parameters[8].DefaultData = &DefaultKeyboardDataQueueSize;
|
||||
Parameters[8].DefaultData = &DefaultPollStatusIterations;
|
||||
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].EntryContext = &DevExt->Settings.OverrideKeyboardType;
|
||||
Parameters[9].EntryContext = &Settings->OverrideKeyboardType;
|
||||
Parameters[9].DefaultType = REG_DWORD;
|
||||
Parameters[9].DefaultData = &DefaultOverrideKeyboardType;
|
||||
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].EntryContext = &DevExt->Settings.OverrideKeyboardSubtype;
|
||||
Parameters[10].EntryContext = &Settings->OverrideKeyboardSubtype;
|
||||
Parameters[10].DefaultType = REG_DWORD;
|
||||
Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype;
|
||||
Parameters[10].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[11].Name = L"MouseDataQueueSize";
|
||||
Parameters[11].EntryContext =
|
||||
&DevExt->MouseAttributes.InputDataQueueLength;
|
||||
Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[11].Name = L"PollingIterations";
|
||||
Parameters[11].EntryContext = &Settings->PollingIterations;
|
||||
Parameters[11].DefaultType = REG_DWORD;
|
||||
Parameters[11].DefaultData = &DefaultMouseDataQueueSize;
|
||||
Parameters[11].DefaultData = &DefaultPollingIterations;
|
||||
Parameters[11].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[12].Name = L"MouseResendStallTime";
|
||||
Parameters[12].EntryContext = &DevExt->Settings.MouseResendStallTime;
|
||||
Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[12].Name = L"PollingIterationsMaximum";
|
||||
Parameters[12].EntryContext = &Settings->PollingIterationsMaximum;
|
||||
Parameters[12].DefaultType = REG_DWORD;
|
||||
Parameters[12].DefaultData = &DefaultMouseResendStallTime;
|
||||
Parameters[12].DefaultData = &DefaultPollingIterationsMaximum;
|
||||
Parameters[12].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[13].Name = L"MouseSynchIn100ns";
|
||||
Parameters[13].EntryContext = &DevExt->Settings.MouseSynchIn100ns;
|
||||
Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[13].Name = L"ResendIterations";
|
||||
Parameters[13].EntryContext = &Settings->ResendIterations;
|
||||
Parameters[13].DefaultType = REG_DWORD;
|
||||
Parameters[13].DefaultData = &DefaultMouseSynchIn100ns;
|
||||
Parameters[13].DefaultData = &DefaultResendIterations;
|
||||
Parameters[13].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[14].Name = L"MouseResolution";
|
||||
Parameters[14].EntryContext = &DevExt->Settings.MouseResolution;
|
||||
Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[14].Name = L"SampleRate";
|
||||
Parameters[14].EntryContext = &Settings->SampleRate;
|
||||
Parameters[14].DefaultType = REG_DWORD;
|
||||
Parameters[14].DefaultData = &DefaultMouseResolution;
|
||||
Parameters[14].DefaultData = &DefaultSampleRate;
|
||||
Parameters[14].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[15].Name = L"SampleRate";
|
||||
Parameters[15].EntryContext = &DevExt->MouseAttributes.SampleRate;
|
||||
Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||
Parameters[15].Name = L"CrashOnCtrlScroll";
|
||||
Parameters[15].EntryContext = &Settings->CrashOnCtrlScroll;
|
||||
Parameters[15].DefaultType = REG_DWORD;
|
||||
Parameters[15].DefaultData = &DefaultSampleRate;
|
||||
Parameters[15].DefaultData = &DefaultCrashOnCtrlScroll;
|
||||
Parameters[15].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[16].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[16].Name = L"NumberOfButtons";
|
||||
Parameters[16].EntryContext = &DevExt->Settings.NumberOfButtons;
|
||||
Parameters[16].DefaultType = REG_DWORD;
|
||||
Parameters[16].DefaultData = &DefaultNumberOfButtons;
|
||||
Parameters[16].DefaultLength = sizeof(ULONG);
|
||||
Status = RtlQueryRegistryValues(
|
||||
RTL_REGISTRY_ABSOLUTE,
|
||||
RegistryPath->Buffer,
|
||||
Parameters,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Parameters[17].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[17].Name = L"EnableWheelDetection";
|
||||
Parameters[17].EntryContext = &DevExt->Settings.EnableWheelDetection;
|
||||
Parameters[17].DefaultType = REG_DWORD;
|
||||
Parameters[17].DefaultData = &DefaultEnableWheelDetection;
|
||||
Parameters[17].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
|
||||
I8042RegistryPath.Buffer,
|
||||
Parameters,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
/* Actually, the defaults are not set when the function
|
||||
* fails, as would happen during setup, so you have to
|
||||
* set them manually anyway...
|
||||
*/
|
||||
RTL_QUERY_REGISTRY_TABLE *Current = Parameters;
|
||||
DPRINT ("Can't read registry: %x\n", Status);
|
||||
while (Current->Name) {
|
||||
*((PULONG)Current->EntryContext) =
|
||||
*((PULONG)Current->DefaultData);
|
||||
Current++;
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Check values */
|
||||
if (Settings->KeyboardDataQueueSize < 1)
|
||||
Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize;
|
||||
if (Settings->MouseDataQueueSize < 1)
|
||||
Settings->MouseDataQueueSize = DefaultMouseDataQueueSize;
|
||||
if (Settings->NumberOfButtons < 1)
|
||||
Settings->NumberOfButtons = DefaultNumberOfButtons;
|
||||
if (Settings->PollingIterations < 0x400)
|
||||
Settings->PollingIterations = DefaultPollingIterations;
|
||||
if (Settings->PollingIterationsMaximum < 0x400)
|
||||
Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum;
|
||||
if (Settings->ResendIterations < 1)
|
||||
Settings->ResendIterations = DefaultResendIterations;
|
||||
}
|
||||
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
{
|
||||
/* Registry path doesn't exist. Set defaults */
|
||||
Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize;
|
||||
Settings->MouseDataQueueSize = DefaultMouseDataQueueSize;
|
||||
Settings->MouseResolution = DefaultMouseResolution;
|
||||
Settings->MouseSynchIn100ns = DefaultMouseSynchIn100ns;
|
||||
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)
|
||||
DevExt->Settings.MouseResolution = 3;
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
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…
Reference in a new issue