This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
Note
This article is for developers who are creating drivers for keyboard and mouse HID clients. If you're looking to fix a mouse or keyboard, see:
This article discusses keyboard and mouse HID client drivers. Keyboards and mice represent the first set of HID clients that were standardized in the HID usage tables and implemented in Windows operating systems.
Keyboard and mouse HID client drivers are implemented in the form of HID mapper drivers. A HID mapper driver is a kernel-mode filter driver that provides a bidirectional interface for I/O requests between a non-HID Class driver and the HID class driver. The mapper driver maps the I/O requests and data protocols of one to the other.
Windows provides system-supplied HID mapper drivers for HID keyboard, and HID mice devices.
The following figure illustrates the system-supplied driver stacks for USB keyboard, mouse, and touchpad devices.
The figure shows the following components:
The system builds the driver stack as follows:
Microsoft provides this guidance for independent hardware vendors (IHVs) writing drivers:
Driver developers are allowed to add more drivers in the form of a filter driver or a new HID client driver.
Filters drivers: Driver developers should ensure that their value-add driver is a filter driver and doesn't replace (or be used in place of) existing Windows HID drivers in the input stack.
Function drivers: Alternatively vendors can create a function driver (instead of a filter driver) but only for vendor specific HID PDOs (with a user mode service if necessary).
Function drivers are allowed in these scenarios:
Transport drivers: Windows team doesn't recommend creating more HID transport minidrivers they're complex to write and maintain. If a partner is creating a new HID transport minidriver, especially on SoC systems, we recommend a detailed architectural review to understand the reasoning and ensure that the driver is developed correctly.
Driver developers should use driver frameworks (KMDF or UMDF) and not rely on WDM for their filter drivers.
Driver developers should reduce the number of kernel-user transitions between their service and the driver stack.
Driver developers should ensure ability to wake the system via both keyboard and touchpad functionality (adjustable by the end user (device manager) or the PC manufacturer). In addition on SoC systems, these devices must be able to wake themselves from a lower powered state while the system is in a working S0 state.
Driver developers should ensure that their hardware is power managed efficiently.
Akeyboard layout fully describes a keyboard's input characteristics for Microsoft Windows 2000 and later versions. For example, a keyboard layout specifies the language, keyboard type and version, modifiers, scan codes, and so on.
See these resources for information about keyboard layouts:
To visualize the layout of a specific keyboard, seeWindows Keyboard Layouts.
For more details around the keyboard layout, visit Control Panel\Clock, Language, and Region\Language.
This list identifies the mouse features supported by Windows:
The method used by Windows to activate the new four and five-button and wheel mode is an extension of the method used to activate the third button and the wheel in IntelliMouse-compatible mice:
The mouse is set to the three-button wheel mode by setting the report rate to 200 reports per second, then to 100 reports per second, then to 80 reports per second. Then, reading the ID from the mouse. The mouse should report an ID of 3 when this sequence is completed.
The mouse is then set to the five-button wheel mode by setting the report rate to 200 reports per second, then to 200 reports per second again, then to 80 reports per second. Then, reading the ID from the mouse. Once the sequence is completed, a five-button wheel mouse should report an ID of 4 (whereas an IntelliMouse-compatible three-button wheel mouse would still report an ID of 3).
This method is applicable to PS/2 mice only, not HID mice. HID mice must report accurate usages in their report descriptor.
Byte | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
1 | Yover | Xover | Ysign | Xsign | Tag | M | R | L | X/Y overflows and signs, buttons |
2 | X7 | X6 | X5 | X4 | X3 | X2 | X1 | X0 | X data byte |
3 | Y7 | Y6 | Y5 | Y4 | Y3 | Y2 | Y1 | Y0 | Y data bytes |
Note
Windows mouse drivers don't check the overflow bits. If there's an overflow, the mouse should send the maximal signed displacement value.
Byte | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | Ysign | Xsign | 1 | M | R | L | X/Y signs and R/L/M buttons |
2 | X7 | X6 | X5 | X4 | X3 | X2 | X1 | X0 | X data byte |
3 | Y7 | Y6 | Y5 | Y4 | Y3 | Y2 | Y1 | Y0 | Y data bytes |
4 | Z7 | Z6 | Z5 | Z4 | Z3 | Z2 | Z1 | Z0 | Z/wheel data byte |
Byte | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | Ysign | Xsign | 1 | M | R | L | X/Y signs and R/L/M buttons |
2 | X7 | X6 | X5 | X4 | X3 | X2 | X1 | X0 | X data byte |
3 | Y7 | Y6 | Y5 | Y4 | Y3 | Y2 | Y1 | Y0 | Y data bytes |
4 | 0 | 0 | B5 | B4 | Z3 | Z2 | Z1 | Z0 | Z/wheel data and buttons 4 and 5 |
Important
The Z/wheel data for a five-button wheel mouse is reduced to four bits instead of the eight bits used in the IntelliMouse-compatible three-button wheel mode. This reduction is made possible by the fact that the wheel typically can't generate values beyond the range +7/-8 during any given interrupt period. Windows mouse drivers sign extend the four Z/wheel data bits when the mouse is in five-button wheel mode. They sign extend the full Z/wheel data byte when the mouse operates in three-button wheel mode.
Buttons 4 & 5 on are mapped to WM_APPCOMMAND messages and correspond to App_Back and App_Forward.
Vendor drivers aren't required for the following devices:
Kbfiltr is used with Kbdclass, the system class driver for keyboard devices and I8042prt, the function driver for a PS/2-style keyboard. Kbfiltr demonstrates how to filter I/O requests and how to add callback routines that modify the operation of Kbdclass and I8042prt.
For more information about Kbfiltr operation, see:
The following IOCTLs are used by Kbfiltr.
The IOCTL_INTERNAL_I8042_HOOK_KEYBOARD request:
The initialization and ISR callbacks are optional and are provided by an upper-level filter driver for a PS/2-style keyboard device.
After I8042prt receives anIOCTL_INTERNAL_KEYBOARD_CONNECT request, it sends a synchronousIOCTL_INTERNAL_I8042_HOOK_KEYBOARD request to the top of the keyboard device stack.
After Kbfiltr receives the hook keyboard request, Kbfiltr filters the request in the following way:
TheIOCTL_INTERNAL_KEYBOARD_CONNECT request connects the Kbdclass service to the keyboard device. Kbdclass sends this request down the keyboard device stack before it opens the keyboard device.
After Kbfiltr received the keyboard connect request, Kbfiltr filters the connect request in the following way:
If the request isn't successful, Kbfiltr completes the request with an appropriate error status.
Kbfiltr provides a template for a filter service callback routine that can supplement the operation ofKeyboardClassServiceCallback, the Kbdclass class service callback routine. The filter service callback can filter the input data that is transferred from the device input buffer to the class data queue.
TheIOCTL_INTERNAL_KEYBOARD_DISCONNECT request is completed with a status of STATUS_NOT_IMPLEMENTED. The Plug and Play manager can add or remove a Plug and Play keyboard.
For all other device control requests, Kbfiltr skips the current IRP stack and sends the request down the device stack without further processing.
Kbfiltr implements the following callback routines.
SeePI8042_KEYBOARD_INITIALIZATION_ROUTINE
TheKbFilter_InitializationRoutine isn't needed if the I8042prt default initialization of a keyboard is sufficient.
I8042prt callsKbFilter_InitializationRoutine when it initializes the keyboard. Default keyboard initialization includes the following operations:
/*ParametersDeviceObject [in]Pointer to the device object that is the context for this callback.SynchFuncContext [in]Pointer to the context for the routines pointed to by ReadPort and Writeport.ReadPort [in]Pointer to the system-supplied PI8042_SYNCH_READ_PORT callback that reads from the port.WritePort [in]Pointer to the system-supplied PI8042_SYNCH_WRITE_PORT callback that writes to the port.TurnTranslationOn [out]Specifies, if TRUE, to turn translation on. Otherwise, translation is turned off.Return valueKbFilter_InitializationRoutine returns an appropriate NTSTATUS code.*/NTSTATUS KbFilter_InitializationRoutine( In PDEVICE_OBJECT DeviceObject, In PVOID SynchFuncContext, In PI8042_SYNCH_READ_PORT ReadPort, In PI8042_SYNCH_WRITE_PORT WritePort, Out PBOOLEAN TurnTranslationOn);
SeePI8042_KEYBOARD_ISR. This callback isn't needed if the default operation of I8042prt is sufficient.
The I8042prt keyboard ISR callsKbFilter_IsrHook after it validates the interrupt and reads the scan code.
KbFilter_IsrHook runs in kernel mode at the IRQL of the I8042prt keyboard.
/*ParametersDeviceObject [in]Pointer to the filter device object of the driver that supplies this callback.CurrentInput [in]Pointer to the input KEYBOARD_INPUT_DATA structure that is being constructed by the ISR.CurrentOutput [in]Pointer to an OUTPUT_PACKET structure that specifies the bytes that are being written to the hardware device.StatusByte [in, out]Specifies the status byte that is read from I/O port 60 when an interrupt occurs.DataByte [in]Specifies the data byte that is read from I/O port 64 when an interrupt occurs.ContinueProcessing [out]Specifies, if TRUE, to continue processing in the I8042prt keyboard ISR after this callback returns; otherwise, processing is not continued.ScanState [in]Pointer to a KEYBOARD_SCAN_STATE structure that specifies the keyboard scan state.Return valueKbFilter_IsrHook returns TRUE if the interrupt service routine should continue; otherwise it returns FALSE.*/KbFilter_IsrHook KbFilter_IsrHook( In PDEVICE_OBJECT DeviceObject, In PKEYBOARD_INPUT_DATA CurrentInput, In POUTPUT_PACKET CurrentOutput, Inout UCHAR StatusByte, In PUCHAR DataByte, Out PBOOLEAN ContinueProcessing, In PKEYBOARD_SCAN_STATE ScanState);
SeePSERVICE_CALLBACK_ROUTINE.
The ISR dispatch completion routine of the function driver callsKbFilter_ServiceCallback, which then calls the keyboard class driver's implementation ofPSERVICE_CALLBACK_ROUTINE. A vendor can implement a filter service callback to modify the input data that is transferred from the device's input buffer to the class data queue. For example, the callback can delete, transform, or insert data.
/*ParametersDeviceObject [in]Pointer to the class device object.InputDataStart [in]Pointer to the first keyboard input data packet in the input data buffer of the port device.InputDataEnd [in]Pointer to the keyboard input data packet that immediately follows the last data packet in the input data buffer of the port device.InputDataConsumed [in, out]Pointer to the number of keyboard input data packets that are transferred by the routine.Return valueNone*/VOID KbFilter_ServiceCallback( In PDEVICE_OBJECT DeviceObject, In PKEYBOARD_INPUT_DATA InputDataStart, In PKEYBOARD_INPUT_DATA InputDataEnd, Inout PULONG InputDataConsumed);
Moufiltr works with Mouclass, the system class driver for mouse devices. It also works with I8042prt, the function driver for a PS/2-style mouse. Both drivers are used with Windows 2000 and later versions. Moufiltr demonstrates how to filter I/O requests and add callback routines that modify the operation of Mouclass and I8042prt.
For more information about Moufiltr operation, see these resources:
The following IOCTLs are used by Moufiltr.
TheIOCTL_INTERNAL_I8042_HOOK_MOUSE request adds an ISR callback routine to the I8042prt mouse ISR. The ISR callback is optional and is provided by an upper-level mouse filter driver.
I8042prt sends this request after it receives anIOCTL_INTERNAL_MOUSE_CONNECT request. I8042prt sends a synchronousIOCTL_INTERNAL_I8042_HOOK_MOUSE request to the top of the mouse device stack.
After Moufiltr receives the hook mouse request, it filters the request in the following way:
The IOCTL_INTERNAL_MOUSE_CONNECT request connects Mouclass service to a mouse device.
Moufiltr completes the IOCTL_INTERNAL_MOUSE_DISCONNECT request with an error status of STATUS_NOT_IMPLEMENTED.
For all other requests, Moufiltr skips the current IRP stack and sends the request down the device stack without further processing.
MouFiltr implements the following callback routines.
SeePI8042_MOUSE_ISR.
/*ParametersDeviceObjectPointer to the filter device object of the driver that supplies this callback.CurrentInputPointer to the input MOUSE_INPUT_DATA structure being constructed by the ISR.CurrentOutputPointer to the OUTPUT_PACKET structure that specifies the bytes being written to the hardware device.StatusByteSpecifies a status byte that is read from I/O port 60 when the interrupt occurs.DataByteSpecifies a data byte that is read from I/O port 64 when the interrupt occurs.ContinueProcessingSpecifies, if TRUE, that the I8042prt mouse ISR continues processing after this callback returns. Otherwise, processing is not continued.MouseStatePointer to a MOUSE_STATE enumeration value, which identifies the state of mouse input.ResetSubStatePointer to MOUSE_RESET_SUBSTATE enumeration value, which identifies the mouse reset substate. See the Remarks section.Return valueMouFilter_IsrHook returns TRUE if the interrupt service routine should continue; otherwise it returns FALSE.*/BOOLEAN MouFilter_IsrHook( PDEVICE_OBJECT DeviceObject, PMOUSE_INPUT_DATA CurrentInput, POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, PBOOLEAN ContinueProcessing, PMOUSE_STATE MouseState, PMOUSE_RESET_SUBSTATE ResetSubState);
AMouFilter_IsrHook callback isn't needed if the default operation of I8042prt is sufficient.
The I8042prt mouse ISR callsMouFilter_IsrHook after it validates the interrupt.
To reset a mouse, I8042prt goes through a sequence of operational substates. A MOUSE_RESET_SUBSTATE enumeration value identifies each substate. For more information about how I8042prt resets a mouse and the corresponding mouse reset substates, see the documentation of MOUSE_RESET_SUBSTATE in ntdd8042.h.
MouFilter_IsrHook runs in kernel mode at the IRQL of the I8042prt mouse ISR.
SeePSERVICE_CALLBACK_ROUTINE
/*ParametersDeviceObject [in]Pointer to the class device object.InputDataStart [in]Pointer to the first mouse input data packet in the input data buffer of the port device.InputDataEnd [in]Pointer to the mouse input data packet immediately following the last data packet in the port device's input data buffer.InputDataConsumed [in, out]Pointer to the number of mouse input data packets that are transferred by the routine.Return valueNone*/VOID MouFilter_ServiceCallback( _In_ PDEVICE_OBJECT DeviceObject, _In_ PMOUSE_INPUT_DATA InputDataStart, _In_ PMOUSE_INPUT_DATA InputDataEnd, _Inout_ PULONG InputDataConsumed);
The ISR DPC of I8042prt calls MouFilter_ServiceCallback, which then calls MouseClassServiceCallback. A filter service callback can be configured to modify the input data that is transferred from the device's input buffer to the class data queue. For example, the callback can delete, transform, or insert data.
Was this page helpful?
Was this page helpful?