Big update of i8042prt driver. The driver is now plug&play compliant and some mouse driver filters may be installed.

svn path=/trunk/; revision=24218
This commit is contained in:
Hervé Poussineau 2006-09-20 18:56:04 +00:00
parent d2241f8ec4
commit f1cf836837
15 changed files with 4119 additions and 2887 deletions

View file

@ -564,13 +564,6 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","ImagePath",0x00020000,"system32
HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Type",0x00010001,0x00000008
; i8042 port driver
HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","Group",0x00000000,"Keyboard Port"
HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt\Parameters","BreakOnSysRq",0x00010001,0x00000001
; Kernel-Mode Tests
;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","ErrorControl",0x00010001,0x00000000
;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Group",0x00000000,"Base"
@ -578,14 +571,8 @@ HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt\Parameters","BreakOnSysRq",0x00
;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Start",0x00010001,0x00000001
;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Type",0x00010001,0x00000001
; Keyboard class driver
HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Group",0x00000000,"Keyboard Class"
HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","ImagePath",0x00020000,"system32\drivers\kbdclass.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Type",0x00010001,0x00000001
; Keyboard parameters
HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass\Parameters","ConnectMultiplePorts",0x00010001,1
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"kbdclass"
; SB16 driver
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Base"
@ -610,14 +597,6 @@ HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ErrorControl",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ImagePath",0x00020000,"system32\drivers\mpu401.sys"
; Mouse class driver
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Group",0x00000000,"Pointer Class"
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","ImagePath",0x00020000,"system32\drivers\mouclass.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"mouclass"
; Mailslot filesystem driver
HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","Group",0x00000000,"File System"

View file

@ -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.

View file

@ -0,0 +1,55 @@
/*
* 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#define NDEBUG
#include <debug.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

View file

@ -1,39 +1,45 @@
#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>
/*-----------------------------------------------------
* DeviceExtension
* Structures
* --------------------------------------------------*/
typedef struct _COMMAND_CONTEXT
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 +48,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 MOUSE_PRESENT 0x02 /* A mouse is attached */
#define KEYBOARD_CONNECTED 0x04 /* Keyboard received IOCTL_INTERNAL_KEYBOARD_CONNECT */
#define MOUSE_CONNECTED 0x08 /* Mouse received IOCTL_INTERNAL_MOUSE_CONNECT */
#define KEYBOARD_STARTED 0x04 /* Keyboard FDO received IRP_MN_START_DEVICE */
#define MOUSE_STARTED 0x08 /* Mouse FDO received IRP_MN_START_DEVICE */
#define KEYBOARD_INITIALIZED 0x10 /* Keyboard interrupt is connected */
#define MOUSE_INITIALIZED 0x20 /* 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,225 +99,390 @@ 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;
} 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;
// 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;
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;
#ifdef __REACTOS__
ULONG DebugKey;
BOOLEAN TabPressed;
#endif
} 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);
VOID NTAPI
i8042SendHookWorkItem(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context);
NTSTATUS I8042ReadDataWait(PDEVICE_EXTENSION DevExt, UCHAR *Data);
NTSTATUS NTAPI
i8042Create(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID I8042Flush();
NTSTATUS NTAPI
i8042Cleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
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);
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);
NTSTATUS NTAPI
i8042Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* keyboard.c */
VOID STDCALL I8042IsrWritePortKbd(PVOID Context,
UCHAR Value);
NTSTATUS STDCALL I8042SynchWritePortKbd(PVOID Context,
UCHAR Value,
BOOLEAN WaitForAck);
NTSTATUS NTAPI
i8042SynchWritePortKbd(
IN PVOID Context,
IN UCHAR Value,
IN BOOLEAN WaitForAck);
BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt,
VOID * Context);
BOOLEAN
i8042KbdStartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID STDCALL I8042DpcRoutineKbd(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2);
NTSTATUS
i8042KbdDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
BOOLEAN STDCALL I8042StartIoKbd(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
i8042KbdInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL I8042InternalDeviceControlKbd(PDEVICE_OBJECT DeviceObject,
PIRP Irp);
BOOLEAN NTAPI
i8042KbdInterruptService(
IN PKINTERRUPT Interrupt,
PVOID Context);
BOOLEAN STDCALL I8042KeyboardEnable(PDEVICE_EXTENSION DevExt);
/* i8042prt.c */
BOOLEAN STDCALL I8042KeyboardEnableInterrupt(PDEVICE_EXTENSION DevExt);
NTSTATUS NTAPI
i8042AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo);
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 */
NTSTATUS NTAPI
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* 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);
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);
NTSTATUS
i8042MouInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID STDCALL I8042MouseHandleButtons(PDEVICE_EXTENSION DevExt,
USHORT Mask);
BOOLEAN NTAPI
i8042MouInterruptService(
IN PKINTERRUPT Interrupt,
PVOID Context);
VOID STDCALL I8042MouseHandle(PDEVICE_EXTENSION DevExt,
UCHAR Output);
VOID NTAPI
i8042MouQueuePacket(
IN PVOID Context);
BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt);
BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt);
BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt);
/* pnp.c */
BOOLEAN
i8042ChangeMode(
IN PPORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR FlagsToDisable,
IN UCHAR FlagsToEnable);
NTSTATUS NTAPI
i8042Pnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* 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 NTAPI
i8042SynchReadPort(
IN PVOID Context,
IN 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_

View file

@ -1,14 +1,18 @@
<module name="i8042prt" type="kernelmodedriver" installbase="system32/drivers" installname="i8042prt.sys">
<bootstrap base="reactos" />
<include base="i8042prt">.</include>
<define name="__USE_W32API" />
<define name="__REACTOS__" />
<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>

View file

@ -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

View file

@ -0,0 +1,68 @@
/*
* 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
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
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 [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
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);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,666 @@
/*
* 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#define NDEBUG
#include <debug.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;
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;
}
/* 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;
/*
* 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;
if (!i8042ChangeMode(DeviceExtension, 0, CCB_KBD_DISAB))
return FALSE;
i8042Flush(DeviceExtension);
/* 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 */
if (!i8042ChangeMode(DeviceExtension, 0, CCB_TRANSLATE))
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++)
{
Status = i8042ReadDataWait(DeviceExtension, &Value);
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;
/* 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 = (PUCHAR)ResourceDescriptor->u.Port.Start.u.LowPart;
DPRINT("Found data port: 0x%lx\n", PortDeviceExtension->DataPort);
FoundDataPort = TRUE;
}
else if (!FoundControlPort)
{
PortDeviceExtension->ControlPort = (PUCHAR)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: /* 0x0 */
{
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) 0x7 */
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
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;
}
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;
}

View file

@ -1,137 +1,141 @@
/*
* 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES ****************************************************************/
#ifndef NDEBUG
#define NDEBUG
#endif
#include <debug.h>
#include "i8042prt.h"
#define NDEBUG
#include <debug.h>
VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input)
/* FUNCTIONS *****************************************************************/
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);
i8042MouQueuePacket(DeviceExtension);
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");
}
}

View file

@ -0,0 +1,218 @@
/*
* 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#define NDEBUG
#include <debug.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 NTAPI
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;
if (Ack != KBD_RESEND)
{
DPRINT1("Unexpected Ack 0x%02x\n", Ack);
return STATUS_UNEXPECTED_IO_ERROR;
}
}
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;
}

View file

@ -1,211 +1,251 @@
/*
* 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES ****************************************************************/
#ifndef NDEBUG
#define NDEBUG
#endif
#include <debug.h>
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#define NDEBUG
#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];
UNICODE_STRING ParametersRegistryKey;
RTL_QUERY_REGISTRY_TABLE Parameters[16];
NTSTATUS Status;
ULONG DefaultHeadless = 0;
ULONG DefaultCrashScroll = 0;
ULONG DefaultCrashSysRq = 0;
ULONG DefaultReportResetErrors = 0;
ULONG DefaultPollStatusIterations = 1;
ULONG DefaultResendIterations = 3;
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 DefaultKeyboardDataQueueSize = 0x64;
UNICODE_STRING DefaultKeyboardDeviceBaseName = RTL_CONSTANT_STRING(L"KeyboardPort");
ULONG DefaultMouseDataQueueSize = 0x64;
ULONG DefaultMouseResolution = 3;
ULONG DefaultSampleRate = 60;
ULONG DefaultMouseSynchIn100ns = 20000000;
ULONG DefaultNumberOfButtons = 2;
ULONG DefaultEnableWheelDetection = 1;
UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerPort");
ULONG DefaultPollStatusIterations = 1;
ULONG DefaultOverrideKeyboardType = 4;
ULONG DefaultOverrideKeyboardSubtype = 0;
ULONG DefaultPollingIterations = 0x400;
ULONG DefaultPollingIterationsMaximum = 12000;
ULONG DefaultResendIterations = 0x3;
ULONG DefaultSampleRate = 60;
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
ParametersRegistryKey.Length = 0;
ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
ParametersRegistryKey.Buffer = ExAllocatePool(PagedPool, ParametersRegistryKey.MaximumLength);
if (!ParametersRegistryKey.Buffer)
{
DPRINT("ExAllocatePool() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;
RtlZeroMemory(Parameters, sizeof(Parameters));
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[0].Name = L"Headless";
Parameters[0].EntryContext = &DevExt->Settings.Headless;
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[0].Name = L"KeyboardDataQueueSize";
Parameters[0].EntryContext = &Settings->KeyboardDataQueueSize;
Parameters[0].DefaultType = REG_DWORD;
Parameters[0].DefaultData = &DefaultHeadless;
Parameters[0].DefaultData = &DefaultKeyboardDataQueueSize;
Parameters[0].DefaultLength = sizeof(ULONG);
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[1].Name = L"CrashOnCtrlScroll";
Parameters[1].EntryContext = &DevExt->Settings.CrashScroll;
Parameters[1].DefaultType = REG_DWORD;
Parameters[1].DefaultData = &DefaultCrashScroll;
Parameters[1].DefaultLength = sizeof(ULONG);
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[1].Name = L"KeyboardDeviceBaseName";
Parameters[1].EntryContext = &Settings->KeyboardDeviceBaseName;
Parameters[1].DefaultType = REG_SZ;
Parameters[1].DefaultData = &DefaultKeyboardDeviceBaseName;
Parameters[1].DefaultLength = 0;
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[2].Name = L"BreakOnSysRq";
Parameters[2].EntryContext = &DevExt->Settings.CrashSysRq;
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[2].Name = L"MouseDataQueueSize";
Parameters[2].EntryContext = &Settings->MouseDataQueueSize;
Parameters[2].DefaultType = REG_DWORD;
Parameters[2].DefaultData = &DefaultCrashSysRq;
Parameters[2].DefaultData = &DefaultMouseDataQueueSize;
Parameters[2].DefaultLength = sizeof(ULONG);
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"MouseResolution";
Parameters[3].EntryContext = &Settings->MouseResolution;
Parameters[3].DefaultType = REG_DWORD;
Parameters[3].DefaultData = &DefaultReportResetErrors;
Parameters[3].DefaultData = &DefaultMouseResolution;
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"MouseSynchIn100ns";
Parameters[4].EntryContext = &Settings->MouseSynchIn100ns;
Parameters[4].DefaultType = REG_DWORD;
Parameters[4].DefaultData = &DefaultPollStatusIterations;
Parameters[4].DefaultData = &DefaultMouseSynchIn100ns;
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"NumberOfButtons";
Parameters[5].EntryContext = &Settings->NumberOfButtons;
Parameters[5].DefaultType = REG_DWORD;
Parameters[5].DefaultData = &DefaultResendIterations;
Parameters[5].DefaultData = &DefaultNumberOfButtons;
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].DefaultType = REG_DWORD;
Parameters[6].DefaultData = &DefaultPollingIterations;
Parameters[6].DefaultLength = sizeof(ULONG);
Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[6].Name = L"PointerDeviceBaseName";
Parameters[6].EntryContext = &Settings->PointerDeviceBaseName;
Parameters[6].DefaultType = REG_SZ;
Parameters[6].DefaultData = &DefaultPointerDeviceBaseName;
Parameters[6].DefaultLength = 0;
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[7].Name = L"PollingIterationsMaximum";
Parameters[7].EntryContext = &DevExt->Settings.PollingIterationsMaximum;
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[7].Name = L"PollStatusIterations";
Parameters[7].EntryContext = &Settings->PollStatusIterations;
Parameters[7].DefaultType = REG_DWORD;
Parameters[7].DefaultData = &DefaultPollingIterationsMaximum;
Parameters[7].DefaultData = &DefaultPollStatusIterations;
Parameters[7].DefaultLength = sizeof(ULONG);
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"OverrideKeyboardType";
Parameters[8].EntryContext = &Settings->OverrideKeyboardType;
Parameters[8].DefaultType = REG_DWORD;
Parameters[8].DefaultData = &DefaultKeyboardDataQueueSize;
Parameters[8].DefaultData = &DefaultOverrideKeyboardType;
Parameters[8].DefaultLength = sizeof(ULONG);
Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[9].Name = L"OverrideKeyboardType";
Parameters[9].EntryContext = &DevExt->Settings.OverrideKeyboardType;
Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[9].Name = L"OverrideKeyboardSubtype";
Parameters[9].EntryContext = &Settings->OverrideKeyboardSubtype;
Parameters[9].DefaultType = REG_DWORD;
Parameters[9].DefaultData = &DefaultOverrideKeyboardType;
Parameters[9].DefaultData = &DefaultOverrideKeyboardSubtype;
Parameters[9].DefaultLength = sizeof(ULONG);
Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[10].Name = L"OverrideKeyboardSubtype";
Parameters[10].EntryContext = &DevExt->Settings.OverrideKeyboardSubtype;
Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[10].Name = L"PollingIterations";
Parameters[10].EntryContext = &Settings->PollingIterations;
Parameters[10].DefaultType = REG_DWORD;
Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype;
Parameters[10].DefaultData = &DefaultPollingIterations;
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"PollingIterationsMaximum";
Parameters[11].EntryContext = &Settings->PollingIterationsMaximum;
Parameters[11].DefaultType = REG_DWORD;
Parameters[11].DefaultData = &DefaultMouseDataQueueSize;
Parameters[11].DefaultData = &DefaultPollingIterationsMaximum;
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"ResendIterations";
Parameters[12].EntryContext = &Settings->ResendIterations;
Parameters[12].DefaultType = REG_DWORD;
Parameters[12].DefaultData = &DefaultMouseResendStallTime;
Parameters[12].DefaultData = &DefaultResendIterations;
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"SampleRate";
Parameters[13].EntryContext = &Settings->SampleRate;
Parameters[13].DefaultType = REG_DWORD;
Parameters[13].DefaultData = &DefaultMouseSynchIn100ns;
Parameters[13].DefaultData = &DefaultSampleRate;
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"CrashOnCtrlScroll";
Parameters[14].EntryContext = &Settings->CrashOnCtrlScroll;
Parameters[14].DefaultType = REG_DWORD;
Parameters[14].DefaultData = &DefaultMouseResolution;
Parameters[14].DefaultData = &DefaultCrashOnCtrlScroll;
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].DefaultType = REG_DWORD;
Parameters[15].DefaultData = &DefaultSampleRate;
Parameters[15].DefaultLength = sizeof(ULONG);
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
ParametersRegistryKey.Buffer,
Parameters,
NULL,
NULL);
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);
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;
DPRINT1 ("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;
Status = RtlDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&DefaultKeyboardDeviceBaseName,
&Settings->KeyboardDeviceBaseName);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status);
}
else
{
Status = RtlDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&DefaultPointerDeviceBaseName,
&Settings->PointerDeviceBaseName);
if (!NT_SUCCESS(Status))
DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status);
}
DPRINT1 ("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;
}

View 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 Hervé Poussineau (hpoussin@reactos.org)
*/
/* NOTE:
* All this file is a big hack and should be removed one day...
*/
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#define NDEBUG
#include <debug.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 = ExAllocatePool(PagedPool, ResourceListSize);
if (!AllocatedResources)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
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_LEVEL_SENSITIVE;
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level = 0;
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector = KEYBOARD_IRQ;
AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Affinity = (KAFFINITY)-1;
/* Create default resource list translated */
AllocatedResourcesTranslated = ExAllocatePool(PagedPool, ResourceListSize);
if (!AllocatedResources)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
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)
ExFreePool(AllocatedResources);
if (AllocatedResourcesTranslated)
ExFreePool(AllocatedResourcesTranslated);
}
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;
cleanup:
if (!NT_SUCCESS(Status))
{
if (Pdo)
IoDeleteDevice(Pdo);
}
return Status;
}