/*++ BUILD Version: 0001 // Increment this if a change has global effects Copyright (c) Microsoft Corporation. All rights reserved. Module Name: ntdd8042.h Abstract: This is the include file that defines all constants and types for hooking i8042 devices. Author: Doron J. Holan (doronh) 17-Dec-1997 Revision History: --*/ #ifndef _NTDD8042_ #define _NTDD8042_ #if _MSC_VER > 1000 #pragma once #endif #ifdef __cplusplus extern "C" { #endif // // Internal IOCTLs used to find who is in the chain of notification // #define IOCTL_INTERNAL_I8042_HOOK_KEYBOARD CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF0, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_INTERNAL_I8042_HOOK_MOUSE CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF0, METHOD_NEITHER, FILE_ANY_ACCESS) // // Internal IOCTLs used to write data to either device // // The IOCTL will be completed when the write has been completed. If the write // time out, the Cancel Routine of the Irp will be ignored and the Irp will still // be completed successfully with a status of STATUS_IO_TIMEOUT instead of // STATUS_SUCCESS // #define IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF1, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF1, METHOD_NEITHER, FILE_ANY_ACCESS) // // Can only be sent down the keyboard stack // #define IOCTL_INTERNAL_I8042_CONTROLLER_WRITE_BUFFER CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF2, METHOD_NEITHER, FILE_ANY_ACCESS) // // The keyboard / mouse will send this down the stack so that the upper device // filter has a device object to synch against. // #define IOCTL_INTERNAL_I8042_KEYBOARD_START_INFORMATION CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF3, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_INTERNAL_I8042_MOUSE_START_INFORMATION CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF3, METHOD_NEITHER, FILE_ANY_ACCESS) // // Valid bits for the PowerCapabilities REG_DWORD that can be put in the devnode // indicating the presence of their respecitve power keys on the device // #define I8042_POWER_SYS_BUTTON 0x0001 #define I8042_SLEEP_SYS_BUTTON 0x0002 #define I8042_WAKE_SYS_BUTTON 0x0004 #define I8042_SYS_BUTTONS (I8042_POWER_SYS_BUTTON | \ I8042_SLEEP_SYS_BUTTON | \ I8042_WAKE_SYS_BUTTON) // // Synchronous reads and writes during kb initialization // #if 0 typedef enum _I8042_PORT_TYPE { PortTypeData = 0, PortTypeCommand } I8042_PORT_TYPE; #endif typedef NTSTATUS (*PI8042_SYNCH_READ_PORT) ( IN PVOID Context, PUCHAR Value, BOOLEAN WaitForACK ); /*++ Routine Description: This routine sends a command or data byte to the keyboard in polling mode. It waits for acknowledgment and resends the command/data if WaitForACK is true. Arguments: Context - Function specific context PortType - If PortTypeCommand, send the byte to the command register, otherwise send it to the data register. WaitForACK - If true, wait for an ACK back from the hardware. AckDeviceType - Indicates which device we expect to get the ACK back from. Value - The byte to send to the hardware. Return Value: STATUS_IO_TIMEOUT - The hardware was not ready for input or did not respond. STATUS_SUCCESS - The byte was successfully sent to the hardware. --*/ typedef NTSTATUS (*PI8042_SYNCH_WRITE_PORT) ( IN PVOID Context, UCHAR Value, BOOLEAN WaitForACK ); // // These functions (PI8042_ISR_WRITE_PORT, PI8042_QUEUE_PACKET) are only valid // when called with the context of the ISR hook // typedef VOID (*PI8042_ISR_WRITE_PORT) ( IN PVOID Context, IN UCHAR Value ); // // Call this function when an input packet has been fully formed and is ready to // be queued to the class driver above of us in the stack // typedef VOID (*PI8042_QUEUE_PACKET) ( IN PVOID Context ); // // Current state of writing to a device // typedef enum _TRANSMIT_STATE { Idle = 0, SendingBytes } TRANSMIT_STATE; // // Current state of writing to the device. If State != Idle, then a write is in // progress // typedef struct _OUTPUT_PACKET { PUCHAR Bytes; ULONG CurrentByte; ULONG ByteCount; TRANSMIT_STATE State; } OUTPUT_PACKET, *POUTPUT_PACKET; typedef enum _MOUSE_STATE { MouseIdle, // expecting byte 1 XMovement, // expecting byte 2 YMovement, // expecting byte 3 ZMovement, // expecting byte 4 (if a wheel mouse) MouseExpectingACK, // expecting ACK from Enable Mouse cmd MouseResetting // reset substate } MOUSE_STATE, *PMOUSE_STATE; /*-- Normal reset process Step Transition into Send Reset to mouse ExpectingReset (ie, 0xAA) Got reset ExpectingResetId Got reset id, send get device id ExpectingGetDeviceIdACK Got get dev id ack, ExpectingGetDeviceIdValue Got dev id ExpectingSetResolutionACK Got ACK for set res ExpectingSetResolutionValueAck Got ACK for value ExpectingSetScaling1to1ACK Got ACK for set scaling ExpectingSetScaling1to1ACK2 Got ACK for set scaling ExpectingSetScaling1to1ACK3 EnableWheelDetection (via registry) == 0 send set sampling rate, ExpectingSetSamplingRateDefaultACK 1 StartPnPIdDetection 2 EnableWheel StartPnPIdDetection, send series ExpectingPnpIdByte1 after setting complete of set sampling rate commands ExpectingPnpIdByte7 compare pnp id to list, if valid, EnableWheel, else set def sampling rate EnableWheel, send series of send get device id after done, set sampling rate commands ExpectingSetSamplingRateDefaultACK got set sampling ack send sampling value got sampling value ack mouse idle ++*/ typedef enum _MOUSE_RESET_SUBSTATE { ExpectingReset = 0, ExpectingResetId, /* 1 */ ExpectingGetDeviceIdACK, /* 2 */ ExpectingGetDeviceIdValue, /* 3 */ ExpectingSetResolutionDefaultACK, /* 4 */ ExpectingSetResolutionDefaultValueACK, /* 5 */ ExpectingSetResolutionACK, /* 6 */ ExpectingSetResolutionValueACK, /* 7 */ ExpectingSetScaling1to1ACK, /* 8 */ ExpectingSetScaling1to1ACK2, /* 9 */ ExpectingSetScaling1to1ACK3, /* 10 */ ExpectingReadMouseStatusACK, /* 11 */ ExpectingReadMouseStatusByte1, /* 12 */ ExpectingReadMouseStatusByte2, /* 13 */ ExpectingReadMouseStatusByte3, /* 14 */ StartPnPIdDetection, /* 15 */ ExpectingLoopSetSamplingRateACK, /* 16 */ ExpectingLoopSetSamplingRateValueACK, /* 17 */ ExpectingPnpIdByte1, /* 18 */ ExpectingPnpIdByte2, /* 19 */ ExpectingPnpIdByte3, /* 20 */ ExpectingPnpIdByte4, /* 21 */ ExpectingPnpIdByte5, /* 22 */ ExpectingPnpIdByte6, /* 23 */ ExpectingPnpIdByte7, /* 24 */ EnableWheel, /* 25 */ Enable5Buttons, /* 26 */ ExpectingGetDeviceId2ACK, /* 27 */ ExpectingGetDeviceId2Value, /* 28 */ ExpectingSetSamplingRateACK, /* 29 */ ExpectingSetSamplingRateValueACK, /* 30 */ ExpectingEnableACK, /* 31 */ ExpectingFinalResolutionACK, /* 32 */ ExpectingFinalResolutionValueACK, /* 33 */ ExpectingGetDeviceIdDetectACK, /* 34 */ ExpectingGetDeviceIdDetectValue, /* 35 */ CustomHookStateMinimum = 100, CustomHookStateMaximum = 999, I8042ReservedMinimum = 1000 } MOUSE_RESET_SUBSTATE, *PMOUSE_RESET_SUBSTATE; /*-- IsrContext -- user provided context CurrentInput -- current packet to being assembled StatusByte -- byte reported by the command port Byte -- byte reported by the mouse (ie, the data port) MouseState -- current state of the i8042prt ISR ResetSubState -- current reset sub state, only valid when MouseState == MouseResetting (otherwise null) ContinueProcessing -- if TRUE, the i8042prt ISR will continue executing after calling the hook ++*/ typedef BOOLEAN (*PI8042_MOUSE_ISR) ( PVOID IsrContext, PMOUSE_INPUT_DATA CurrentInput, POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR Byte, PBOOLEAN ContinueProcessing, PMOUSE_STATE MouseState, PMOUSE_RESET_SUBSTATE ResetSubState ); typedef struct _INTERNAL_I8042_HOOK_MOUSE { // // Context variable for IsrRoutine, CancelRoutine // OUT PVOID Context; // // Routine to call when a byte is received via the interrupt // OUT PI8042_MOUSE_ISR IsrRoutine; // // Write function, will automatically write to the command port saying the // next byte is directed towards the auxilliary device. // // NB: May only called within the context of the IsrRoutine provided above // The mouse's response to the write will passed to the IsrRoutine when // it is received (ie, if 0xF4 (enable) was written using this function, // an 0xFA (ACK) will be passed to IsrRoutine if the enable was // successful) // IN PI8042_ISR_WRITE_PORT IsrWritePort; // // Queue the current packet (ie the one passed into the isr callback hook) // to be reported to the class driver // IN PI8042_QUEUE_PACKET QueueMousePacket; // // Context for IsrWritePort, QueueMousePacket // IN PVOID CallContext; } INTERNAL_I8042_HOOK_MOUSE, *PINTERNAL_I8042_HOOK_MOUSE; // // Define the keyboard scan code input states. // typedef enum _KEYBOARD_SCAN_STATE { Normal, GotE0, GotE1 } KEYBOARD_SCAN_STATE, *PKEYBOARD_SCAN_STATE; typedef NTSTATUS (*PI8042_KEYBOARD_INITIALIZATION_ROUTINE) ( IN PVOID InitializationContext, IN PVOID SynchFuncContext, IN PI8042_SYNCH_READ_PORT ReadPort, IN PI8042_SYNCH_WRITE_PORT WritePort, OUT PBOOLEAN TurnTranslationOn ); typedef BOOLEAN (*PI8042_KEYBOARD_ISR) ( PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR Byte, PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState ); typedef struct _INTERNAL_I8042_HOOK_KEYBOARD { // // Context variable for all callback routines // OUT PVOID Context; // // Routine to call after the mouse is reset // OUT PI8042_KEYBOARD_INITIALIZATION_ROUTINE InitializationRoutine; // // Routine to call when a byte is received via the interrupt // OUT PI8042_KEYBOARD_ISR IsrRoutine; // // Write function // IN PI8042_ISR_WRITE_PORT IsrWritePort; // // Queue the current packet (ie the one passed into the isr callback hook) // to be reported to the class driver // IN PI8042_QUEUE_PACKET QueueKeyboardPacket; // // Context for IsrWritePort, QueueKeyboardPacket // IN PVOID CallContext; } INTERNAL_I8042_HOOK_KEYBOARD, *PINTERNAL_I8042_HOOK_KEYBOARD; typedef struct _INTERNAL_I8042_START_INFORMATION { // // Size of this structure // ULONG Size; // // Interrupt object for the device. Should only be used for calls to // KeSynchronizeExecution // PKINTERRUPT InterruptObject; // // Future use // ULONG Reserved[8]; } INTERNAL_I8042_START_INFORMATION, *PINTERNAL_I8042_START_INFORMATION; #ifdef __cplusplus } #endif #endif // _NTDD8042_